当操作系统进入内核模式时,会发生什么?

5
我发现我的教科书或谷歌搜索技能都无法给我这个问题的一个恰当答案,虽然它依赖于操作系统,但是一般来说会发生什么,以及为什么会发生呢?
我的教科书说,系统调用会导致操作系统进入内核模式,前提是不在内核模式下。这是必需的,因为内核模式才能控制I/O设备和其他不属于特定进程地址空间的东西。但如果我理解正确,切换到内核模式并不一定意味着进程上下文切换(保存进程的当前状态到CPU以外的其他位置,以便运行其他进程)。
为什么会这样?我曾经想过可能有一些“管理员”进程被切换进来,负责处理进程的系统调用,并将结果发送到进程的地址空间,但我猜想我错了。我似乎无法理解在切换到和从内核模式中实际上发生了什么,以及这如何影响进程对I/O设备的操作能力。
谢谢 :)
编辑:额外问题:库调用是否一定会结束在系统调用中?如果没有,您有没有任何不以系统调用结束的库调用的示例?如果有,为什么我们要使用库调用?
1个回答

6
历史上系统调用一般使用中断来发起。Linux使用 0x80 向量,而Windows则使用 0x2F 向量来访问系统调用,并将函数的索引存储在 eax 寄存器中。近年来,我们开始使用 SYSENTERSYSEXIT 指令。用户应用程序运行在 Ring3 或用户空间/用户模式下。CPU 在这里非常棘手,从内核模式切换到用户模式需要特殊的处理。它实际上涉及欺骗 CPU ,使其认为是从用户模式发出的,当发出一个称为 iret 的特殊指令时。从用户模式返回内核模式的唯一方法是通过中断或已经提到的 SYSENTER/EXIT 指令对。它们都使用一个名为 TaskStateSegmentTSS 的特殊结构。这些可以使 CPU 找到内核堆栈所在的位置,因此,它本质上需要进行任务切换。 但实际上会发生什么? 当您发出系统调用时,CPU 会查找 TSS,获取其 esp0 值(内核的堆栈指针),并将其放入 esp 中。然后,CPU 在另一个特殊结构中查找中断向量的索引,该结构称为 InterruptDescriptorTableIDT,并找到一个地址。这个地址是处理系统调用的函数所在的地方。CPU 推送标志寄存器、代码段、用户堆栈和下一个指令的指针,该指令在 int 指令之后。系统调用完成后,内核发出 iret。然后 CPU 返回到用户模式,并继续正常运行您的应用程序。 所有库调用是否都以系统调用结尾? 大多数库调用会以系统调用结束,但也有一些不会。例如,请看 memcpy 和其他函数。

1
非常感谢!回答很好 :) 但是为什么切换到内核模式比普通的进程上下文切换要耗费更多时间呢?两者不都是做同样的事情吗:交换寄存器、调用栈等等? - user1747330
因为需要使用 TSS 进行硬件辅助任务切换,而硬件切换已经不再更新,因此比软件任务切换慢得多。 - Levente Kurusa
1
同时,TSS的指针位于GDT中,因此它需要更多的内存访问。 - Levente Kurusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接