内核栈的作用是什么?

12
以下是我阅读的有关进程A和进程B之间发生上下文切换的描述。我不理解内核栈的用途。应该有一个针对每个进程的内核栈。我正在阅读的描述中提到了将A的寄存器保存在A的内核栈上,还将A的寄存器保存到A的进程结构中。保存寄存器到内核栈和进程结构的目的是什么?为什么需要这两者?

上下文切换概念上很简单:操作系统只需为当前正在执行的进程(例如,将其寄存器值保存到其内核栈中)保存几个寄存器值,并为即将执行的进程(从其内核栈中)恢复一些寄存器值。通过这样做,操作系统确保当最终执行返回中断指令时,系统不会返回到正在运行的进程,而是恢复其他进程的执行...

进程A正在运行,然后被定时器中断打断。硬件保存其寄存器(保存到其内核栈中),并进入内核(切换到内核模式)。在定时器中断处理程序中,操作系统决定将运行进程A切换到进程B。此时,它调用switch()例程,谨慎地保存当前寄存器值(保存到A的进程结构中),恢复进程B的寄存器(从其进程结构条目中),然后切换上下文,具体是通过将堆栈指针更改为使用B的内核栈(而不是A的)。最后,操作系统返回中断,恢复B的寄存器并开始运行它。


1
[so] 不是一个学习操作系统内部原理的好网站。 - John Saunders
1
概念!=现实。内核会切换到自己的堆栈,以便不将其内部堆栈要求强加到它管理的每个线程的堆栈上。内核堆栈不是存储线程上下文数据(如GP寄存器)的地方 - 必须有一个单独的结构来存储每个线程的上下文。典型的堆栈上下文远比中断线程的GP寄存器和/或堆栈指针要大得多。 - Martin James
2个回答

14
我对第二段内容有所争议。
Process A正在运行,然后被定时器中断打断。硬件会将其寄存器(存放在内核栈上)保存并进入内核(切换到内核模式)。
我不知道有哪个系统可以在中断时将所有寄存器都保存在内核栈上。通常,处理器在中断后只在内核栈上保存最少量的必要状态。然后,中断处理程序会在退出之前保存它想要使用的任何其他寄存器,并在退出时恢复它们。处理器的“从中断或异常返回”指令会自动恢复由中断自动存储的寄存器。
这个描述假设进程没有改变。
如果中断处理程序决定更改进程,则保存当前的寄存器状态(“进程上下文”,大多数处理器都有一个单独的指令)。在英特尔领域中,您可能需要使用多个指令),然后执行另一个指令以加载新进程的进程上下文。
回答您的标题问题“内核栈用于什么?”它在处理器处于内核模式时使用。如果内核没有受保护免受用户访问的堆栈,则系统的完整性可能会受到损害。内核栈往往非常小。
回答你的第二个问题,“将寄存器保存到内核栈和进程结构中的确切目的是什么,为什么需要两者?”
它们用于两个不同的目的。在内核栈上保存的寄存器用于退出内核模式。上下文进程块中保存整个寄存器集,以便更改进程。
我认为你的误解来自源代码措辞的措辞,这表明进入内核模式时将所有寄存器都存储在堆栈上,而不仅仅是必要的最少数量的寄存器,以进行内核模式切换。系统通常只会保存返回到用户模式所需的内容(并且可能在另一个上下文切换中使用相同的信息返回到原始进程)。进程上下文的更改则保存了所有寄存器。
回答额外的问题:
如果中断处理程序需要使用CPU自动未保存的寄存器,它会在进入时将它们推送到内核栈上,并在退出时将它们弹出。中断处理程序必须显式保存和恢复任何[通用]寄存器。 进程上下文块不会被触及。
进程上下文块仅作为实际上下文切换的一部分而被更改。
例如:
假设我们有一台带有程序计数器、堆栈指针、处理器状态和16个通用寄存器的处理器(我知道没有这样的系统),并且所有模式都使用相同的SP。
1. 中断发生。
硬件将PC、SP和PS推入堆栈,并从中断处理程序(从处理器的分派表中)加载SP的地址和PC。
2. 调用中断处理程序。
处理程序编写者决定要使用R0-R3。因此,处理程序的第一行为:
Push R0  ; on to the kernel mode stack
Push R1
Push R2
Push R3
  1. 中断处理程序可以执行任何想要执行的操作。

  2. 清理工作

编写中断处理程序的人需要做的事情:

Pop R3
Pop R2
Pop R1
Pop R0 
REI      ; Whatever the system's return from interrupt or exception instruction is.
  1. 硬件接管

从内核模式堆栈中恢复PS、PC和SP,然后在中断前继续执行。

为简化起见,我自己设计了一个处理器。某些处理器具有可中断的长指令(例如块字符移动)。这种指令通常使用寄存器来维护其上下文。在这样的系统上,处理器必须自动保存用于在指令中维护上下文所使用的任何寄存器。

除非正在更改进程,否则中断处理程序不会与进程上下文块交互。


我同意你的看法,我也对第二段有些分歧。不管怎样,点个赞。 - Am_I_Helpful
1
如果中断处理程序保存了任何额外的寄存器以供使用,它会将它们保存在哪里?它是将它们放入进程控制块中吗?而从中断返回指令会恢复这些寄存器,那么从中断返回指令如何知道如何恢复这些寄存器呢?它是否理解进程控制块的格式并从中恢复寄存器? - user782220
上面的答案解释了"进程结构入口"和"内核栈"之间的功能差异,并且原始问题引用似乎来自OSTEP第6章。希望有人可以根据书本对答案进行改进,如果有改进的话。 - zg c

-1

谈论操作系统的内部工作方式是困难的,因为它取决于硬件的工作方式。此外,术语并没有高度标准化。

我猜作者所说的“进程结构条目”是指进程的“上下文”,这是包含每个寄存器副本的东西。中断代码不可能立即将寄存器保存到该结构中,因为在这样做时它必须使用(并因此修改)寄存器。这就是为什么它必须保存一些寄存器,足以完成工作,在某个立即可用的地方,例如栈指针所指向的位置,作者称之为“内核栈”。

根据架构的不同,这可以是单个堆栈或每个进程的单独堆栈。


2
在这里你不能瞎猜。如果有任何疑问,请向原帖提出更多澄清要求。要么确信无疑,要么就不要回答。 - Am_I_Helpful

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