内核栈有啥用?
Posted
技术标签:
【中文标题】内核栈有啥用?【英文标题】:What is a kernel stack used for?内核栈有什么用? 【发布时间】:2015-08-05 20:15:55 【问题描述】:以下是我读到的关于进程 A 和进程 B 之间的上下文切换的描述。我不明白内核堆栈的用途。假设有一个每个进程的内核堆栈。我正在阅读的描述谈到将 A 的寄存器保存到 A 的内核堆栈中,并将 A 的寄存器保存到 A 的进程结构中。将寄存器保存到内核堆栈和进程结构到底有什么意义?为什么两者都需要?
上下文切换在概念上很简单:操作系统所要做的就是保存 当前正在执行的进程的一些寄存器值(到它的 内核堆栈,例如)并为 即将执行的进程(来自其内核堆栈)。通过这样做, 操作系统因此确保当从陷阱返回指令最终 执行,而不是返回到正在运行的进程, 系统恢复执行另一个进程...
进程 A 正在运行,然后被定时器中断中断。 硬件保存它的寄存器(到它的内核栈上)并进入 内核(切换到内核模式)。在定时器中断处理程序中, 操作系统决定从正在运行的进程 A 切换到进程 B。 点,它调用 switch() 例程,它小心地保存当前 寄存器值(进入A的进程结构),恢复 进程 B 的寄存器(来自其进程结构条目),然后 切换上下文,特别是通过更改要使用的堆栈指针 B 的内核堆栈(而不是 A 的)。最后,操作系统从陷阱中返回, 这会恢复 B 的寄存器并开始运行它。
【问题讨论】:
Stack Overflow 不是学习操作系统内部知识的好网站。 概念!=现实。内核切换到自己的堆栈,以免将自己的内部堆栈要求强加到它管理的每个线程的堆栈上。无论如何,内核堆栈不是像 GP 寄存器那样存储线程上下文数据的地方——必须有一个单独的结构来存储每个线程的上下文。典型的堆栈上下文比中断线程的 GP 寄存器和/或堆栈指针大得多。 【参考方案1】:我对第二段有不同意见。
进程 A 正在运行,然后被定时器中断中断。硬件保存它的寄存器(到它的内核堆栈上)并进入内核(切换到内核模式)。
我不知道有一个系统会在中断时将所有寄存器保存在内核堆栈上。程序计数器、处理器状态和堆栈指针(假设硬件没有单独的内核模式堆栈指针)。通常,处理器在中断后将所需的最小值保存在内核堆栈上。然后,中断处理程序将保存它想要使用的任何其他寄存器,并在退出前恢复它们。处理器的 RETURN FROM INTERRUPT 或 EXCEPTION 指令然后恢复由中断自动存储的寄存器。
该描述假定流程没有变化。
如果中断句柄决定改变进程,它会保存当前的寄存器状态(“进程上下文”——大多数处理器为此只有一条指令。在英特尔领域,您可能必须使用多条指令)然后执行另一个加载新进程的进程上下文的指令。
要回答您的标题问题“内核堆栈用于什么?”,只要处理器处于内核模式,就会使用它。如果内核没有防止用户访问的堆栈,系统的完整性可能会受到损害。内核堆栈往往非常小。
回答您的第二个问题,“将寄存器同时保存到内核堆栈和进程结构的意义何在?为什么两者都需要?”
它们有两个不同的目的。内核堆栈上保存的寄存器用于退出内核模式。上下文进程块保存整个寄存器集以更改进程。
我认为您的误解来自您的来源的措辞,即当进入内核模式时,所有寄存器都存储在堆栈中,而不仅仅是进行内核模式切换所需的最小数量的寄存器。系统通常只会保存返回到用户模式所需的内容(并且可能使用相同的信息在另一个上下文切换中返回到原始进程,具体取决于系统)。进程上下文的变化保存了所有的寄存器。
编辑以回答其他问题:
如果中断处理程序需要使用未被中断自动保存的寄存器,它会在进入时将它们压入内核堆栈,并在退出时将它们弹出。中断处理程序必须显式保存和恢复它使用的任何 [通用] 寄存器。 Process Context Block 不会因此而受到影响。
进程上下文块仅作为实际上下文切换的一部分进行更改。
例子:
假设我们有一个带有程序计数器、堆栈指针、处理器状态和 16 个通用寄存器的处理器(我知道不存在这样的系统),并且所有模式都使用相同的 SP。
-
发生中断。
硬件将 PC、SP 和 PS 推入堆栈,将内核模式堆栈的地址和来自中断处理程序(来自处理器的调度表)的 PC 加载到 SP。
-
中断处理程序被调用。
处理程序的编写者决定他要去我们 R0-R3。所以处理程序的第一行有:
Push R0 ; on to the kernel mode stack
Push R1
Push R2
Push R3
中断处理程序做它想做的任何事情。
清理
中断处理程序的编写者需要做的:
Pop R3
Pop R2
Pop R1
Pop R0
REI ; Whatever the system's return from interrupt or exception instruction is.
-
硬件接管
从内核模式堆栈中恢复 PS、PC 和 SP,然后从中断前的位置恢复执行。
为简化起见,我已经制作了自己的处理器。一些处理器具有可中断的冗长指令(例如块字符移动)。此类指令通常使用寄存器来维护它们的上下文。在这样的系统上,处理器必须自动保存所有用于维护指令上下文的寄存器。
除非正在更改进程,否则中断处理程序不会混淆进程上下文块。
【讨论】:
我同意你的观点,我对第二段也有不同意见。无论如何,+1。 如果中断处理程序保存了它想要使用的任何其他寄存器,它在哪里保存它们?是否将它们放入过程控制块中。而中断返回指令恢复了那些寄存器,中断返回指令怎么知道如何恢复那些寄存器呢?它是否理解进程控制块格式并从那里恢复寄存器?【参考方案2】:很难笼统地谈论操作系统“幕后”的工作方式,因为它取决于硬件的工作方式。此外,术语不是高度标准化的。
我的猜测是,通过“流程结构条目”,作者的意思是通常称为流程的“上下文”,其中包含每个寄存器的副本。中断代码不可能立即将寄存器保存到此结构中,因为这样做必须使用(并因此修改)寄存器。这就是为什么它必须保存一些寄存器,足以让它可以在某个立即可用的地方完成这项工作,例如堆栈指针指向的位置,作者称之为“内核堆栈”。
根据架构,这可能是单个堆栈或每个进程单独的堆栈。
【讨论】:
你没有选择在这里猜测。如果有任何疑问,请向 OP 寻求更多澄清。要么确定,要么根本不回答。以上是关于内核栈有啥用?的主要内容,如果未能解决你的问题,请参考以下文章
lunux网卡驱动中的NETIF_F_HW_VLAN_CTAG_RX和NETIF_F_HW_VLAN_CTAG_TX有啥用?