CPU从用户模式切换到内核模式:它具体做了什么?它如何进行这个转换?

30
CPU从用户模式切换到内核模式:它到底做了什么?它如何进行这种转换?
编辑:即使它是与体系结构相关的,请为我提供答案。体系结构由您决定。告诉我您熟悉的体系结构。
我想了解其中涉及哪些内容。

1
它是依赖于架构而不一定依赖于操作系统。 - Nathan Osman
4个回答

37

注意:这主要与x86架构有关。以下是一个相对简化的解释。

通常情况下,转换是由以下之一引起的:

  • 错误(例如,页错误或执行指令引起的其他异常)
  • 中断(例如,键盘中断或I/O完成)
  • 陷阱(例如,系统调用)

通常发生的情况是系统检查中断描述符表(IDT)。每个异常(中断、错误等)都有一个与其关联的数字,用于对此表进行索引。

通过此表,CPU 可以确定要运行的中断处理程序。

作为转换的一部分,以下更改(通常)会生效:

  • 切换到内核堆栈
  • EFLAGS被保存
  • 代码段选择器和 EIP 被保存。
  • 堆栈段选择器和堆栈指针被保存
  • 开始执行中断处理程序
  • 通用寄存器被保存(处理程序的工作)
  • 段选择器更改为内核模式(处理程序的工作)

现在你处于内核模式。

希望有所帮助 :)


1
在执行中断处理程序时,中断是否被禁用? 或者更高优先级的中断是否允许打断已经运行的中断处理程序?在执行中断处理程序期间是否可能发生上下文切换? - Sharat Chandra
只是澄清一下:当你写“系统检查中断描述符表”时,你的意思是“操作系统”吗? - Martin Thoma

4

这取决于系统,但通常的机制是某些用户操作会引起软件中断。该中断使处理器切换模式并跳转到内核代码,然后检查程序试图执行什么操作(系统调用?),然后执行请求的操作并跳回用户模式代码。除了软件中断之外,其他机制也可能导致过渡;例如,在抢占式多任务系统中,定时器中断可能触发调度程序运行。


那么,这两种情况是 CPU 进入内核模式的唯一情况吗? - claws
@claws,这完全取决于处理器、操作系统和实现方式。 - Carl Norum
关于系统调用通过中断发生的评论有些过时了。旧版Linux曾使用中断0x80在系统调用时切换到内核模式。但是随着新处理器(其中新的是任何> pentium 2)和Linux内核的出现,转向使用通过sysenter、sysexit指令提供的“快速系统调用”功能。请查看http://articles.manugarg.com/systemcallinlinux2_6.html。 - Jasmeet
@Jasmeet,即使在英特尔的行话中没有相同的名称,它仍然在语义上等同于软件中断。 - Carl Norum

3
我的理解是,任何其段寄存器的两个LSB为零的程序都将在内核模式下运行,而任何其段寄存器的两个LSB = 1的程序都将在用户模式下运行。实际上,段寄存器的两个LSB定义特权级别(0最高到3最低)。
因此,要使程序在内核模式下运行,您必须设置段寄存器为0010十六进制(我认为是这样)。我不确定如何在不覆盖其他内容的情况下将程序放置在该内存空间中 - 换句话说,链接器如何确保这一点?
此外,如果您想从用户模式代码调用内核模式代码,您必须找出如何传递参数 - 它们不使用相同的内存空间,因此无法通过内存引用传递数据。我猜你得用寄存器传递。
如果有人可以填补上述的空白,我将非常感激。

1
在Windows中,当您进行系统调用时,库例程会调用驻留在操作系统地址空间中的内核入口点。它反过来通过执行特定于此目的的指令(例如sysenter)将CPU置于监管模式。它所做的基本上是设置标志寄存器中的一个位。这使得操作系统能够使用特权指令。

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