use*_*306 10 stack operating-system kernel
在同一个程序中使用两个不同堆栈的需求是什么?陷阱如何将当前的程序堆栈从用户堆栈更改为内核堆栈?完成系统调用后,它如何回到用户堆栈?
每个进程都有内核和用户堆栈吗?
Bra*_*rad 12
每个CPU有一个"内核堆栈".每个进程都有一个"用户堆栈",尽管每个线程都有自己的堆栈,包括用户和内核线程.
"陷阱如何改变堆栈"实际上非常简单.
由于中断,CPU会更改进程或"模式".中断可能由于许多不同原因发生 - 发生故障(如错误或页面错误),或物理硬件中断(如来自设备) - 或定时器中断(例如在使用进程时发生)所有这些都分配了CPU时间").
无论哪种方式 - 当调用此中断时,CPU寄存器都保存在堆栈中 - 所有寄存器 - 包括堆栈指针本身.
通常,然后调用"调度程序".然后,调度程序选择另一个要运行的进程 - 恢复其所有已保存的寄存器,包括堆栈指针,并从它停止的位置继续执行(存储在返回地址指针中).
这称为"上下文切换".
我正在简化一些事情 - 比如如何保存和恢复内存管理上下文,但这就是主意.它只是保存和恢复寄存器以响应中断 - 包括"堆栈指针"寄存器.
小智 10
有2个堆栈,因为有2个CPU执行上下文.用户模式堆栈将满足您的程序关于为函数,局部变量,返回地址等创建堆栈帧.当CPU将上下文切换到内核模式时,例如在系统调用执行期间,它需要访问内核内存和数据结构然后切换到使用它的内核堆栈.是的,我认为Unix使用每进程内核堆栈.
我在大学学习OS,我们的项目基于哈佛构建的OS/161。所以我的答案都是基于这个操作系统。
在 OS/161 中,每个线程有2 个堆栈- 一个用于用户/应用程序,一个用于内核程序。
1. 在同一个程序中使用两个不同的堆栈有什么需要?假设我们只在应用程序模式下使用堆栈。由于内存空间是由多个线程共享的,如果其他线程不小心覆盖了内核使用的地址,那么内核可能会崩溃,从而导致操作系统非常脆弱。
2、trap如何将当前程序栈从用户栈变为内核栈?在 OS/161 中,trap 用于从应用程序传输到内核。有三种机制可以调用 trap:系统调用、异常和中断。内核堆栈中的陷阱帧用于保存当前线程上下文。
以下是详细过程(来自UWaterloo CS350的讲义):
当上述机制之一发生时,硬件将 CPU 切换到特权模式并将控制转移到预定义的位置,内核处理程序应位于该位置。
内核处理程序创建一个陷阱帧并使用它来保存应用程序线程上下文,以便可以在 CPU 上执行处理程序代码。
就在内核处理程序完成执行之前,它从陷阱帧恢复应用程序线程上下文,然后将控制权返回给应用程序。
上面的过程也清楚地解释了这个问题。