内核栈有什么用?

What is a kernel stack used for?

下面是我读到的关于进程A和进程B的上下文切换的描述。我不明白内核栈是干什么用的。假设每个进程都有一个内核堆栈。我正在阅读的描述谈到将 A 的寄存器保存到 A 的内核堆栈中,并将 A 的寄存器保存到 A 的进程结构中。将寄存器保存到内核堆栈和进程结构以及为什么需要两者?

A context switch is conceptually simple: all the OS has to do is save a few register values for the currently-executing process (onto its kernel stack, for example) and restore a few for the soon-to-be-executing process (from its kernel stack). By doing so, the OS thus ensures that when the return-from-trap instruction is finally executed, instead of returning to the process that was running, the system resumes execution of another process...

Process A is running and then is interrupted by the timer interrupt. The hardware saves its registers (onto its kernel stack) and enters the kernel (switching to kernel mode). In the timer interrupt handler, the OS decides to switch from running Process A to Process B. At that point, it calls the switch() routine, which carefully saves current register values (into the process structure of A), restores the registers of Process B (from its process structure entry), and then switches contexts, specifically by changing the stack pointer to use B’s kernel stack (and not A’s). Finally, the OS returns-from-trap, which restores B’s registers and starts running it.

很难笼统地谈论 OS 的工作原理 'under the hood',因为它取决于硬件的工作原理。此外,术语不是高度标准化的。

我的猜测是,'Process structure entry' 作者指的是通常所说的 'context' 进程,它包含每个寄存器的副本。中断代码不可能立即将寄存器保存到这个结构中,因为这样做必须使用(并因此修改)寄存器。这就是为什么它必须保存一些寄存器,足以让它可以在立即可用的地方完成这项工作,例如堆栈指针指向的位置,作者称之为 'kernel stack'。

根据体系结构,这可能是单个堆栈或每个进程的单独堆栈。

第二段我有异议

Process A is running and then is interrupted by the timer interrupt. The hardware saves its registers (onto its kernel stack) and enters the kernel (switching to kernel mode).

我不知道有哪个系统会在中断时将所有寄存器保存在内核堆栈中。程序计数器、处理器状态和堆栈指针(假设硬件没有单独的内核模式堆栈指针)。通常,处理器在中断后将最少的必要信息保存在内核堆栈中。然后中断处理程序将保存它想要使用的任何其他寄存器并在退出前恢复它们。然后处理器的 RETURN FROM INTERRUPT 或 EXCEPTION 指令恢复中断自动存储的寄存器。

该描述假设流程没有变化。

如果中断句柄决定改变进程,它会保存当前寄存器状态("process context"——大多数处理器为此只有一条指令。在 Intel 领域,您可能必须使用多条指令)然后执行另一条指令加载新进程的进程上下文。

为了回答您的标题问题 "What is a kernel stack used for?",只要处理器处于内核模式,就会使用它。如果内核没有保护堆栈免受用户访问,则系统的完整性可能会受到损害。内核堆栈往往很小。

回答你第二个问题,"What exactly is the point of saving the registers to both the kernel stack and the process structure and why the need for both?"

它们有两个不同的用途。内核堆栈上保存的寄存器用于退出内核模式。上下文进程块保存整个寄存器集,以便更改进程。

我认为您的误解来自于您的源代码的措辞,该措辞暗示进入内核模式时所有寄存器都存储在堆栈中,而不仅仅是进行内核模式切换所需的最小数量的寄存器。系统通常只会保存返回用户模式所需的内容(并且可能会使用相同的信息 return 在另一个上下文切换中返回到原始进程,具体取决于系统)。进程上下文的改变保存了所有的寄存器。

编辑以回答其他问题:

如果中断处理程序需要使用未由中断自动保存的 CPU 寄存器,它会在进入时将它们压入内核堆栈,并在退出时弹出它们。中断处理程序必须显式保存和恢复它使用的任何[通用]寄存器。流程上下文块不会为此受到影响。

进程上下文块仅作为实际上下文切换的一部分进行更改。

示例:

假设我们有一个带有程序计数器、堆栈指针、处理器状态和 16 个通用寄存器的处理器(我知道实际上不存在这样的系统)并且所有模式都使用相同的 SP。

  1. 发生中断。

硬件将 PC、SP 和 PS 压入堆栈,用内核模式堆栈的地址和来自中断处理程序的 PC(来自处理器的调度 table).

  1. 调用中断处理程序。

处理程序的编写者决定他将转到我们 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,然后从中断前的位置恢复执行。

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

中断处理程序不会与进程上下文块混为一谈,除非它正在更改进程。