我的意思是,在操作系统 API 的核心深处,程序从操作系统请求的每个基本功能是否都有中断“调用”?
2 回答
Yes, there very often is such an interrupt.
Interrupt and exception handlers and system calls are often implemented using the same mechanism. The reason for this is that in all these cases the control has to be transferred into the kernel and a number of registers has to be preserved before and restored after the handling of the event. Interrupt handling occurs in the kernel, is ubiquitous (rare CPUs don't support interrupts) and it's a natural choice for interrupt handling, exception handling and system calls.
What's more, in some cases it's desirable to invoke system calls from already within the kernel.
In Windows, for example, kernel code often has an option of calling either ZwFoo()
or NtFoo()
, where Foo
is some meaningful function name and Zw
and Nt
are name prefixes, differentiating between the two versions of Foo()
. If ZwFoo()
is chosen, Foo()
is called directly. OTOH, if NtFoo()
is chosen, the control first has to go through the system call (AKA trap) mechanism/code and only then will it reach the actual Foo()
. The choice between the two versions has to do with something called Previous Mode
.
A few words on Previous Mode
... Kernel code is trusted. User code is untrusted. When Foo()
is called from user mode, the kernel will do its best to validate all untrusted inputs and check that all the permissions are in place before doing what's requested. That's how it's ought to be. Now the kernel itself sometimes needs to call Foo()
. If it calls Foo()
on behalf of itself, a number of rigorous checks don't need to be made. But if it calls Foo()
on behalf of user code with inputs from user mode (and all that is untrusted), those checks must be made. Hence, depending on the situation the kernel calls either ZwFoo()
or NtFoo()
. When NtFoo()
is called PreviousMode
gets set to UserMode
and that signals the necessity of the aforementioned checks. When ZwFoo()
is called, PreviousMode
remains UserMode
for user mode callers or gets set to KernelMode
for kernel mode callers. So, user mode callers can't avoid the checks but the kernel has a choice of doing them (when they are necessary) or not (when they aren't).
至少在 Linux 上有系统调用。当用户空间想要从内核中获得某些东西时,它会发出一个软件中断0x80
,其中包含它想要在寄存器中调用的函数的索引。