我想通过这个问题来学习和填补我知识的空白。
因此,一个用户正在运行一个线程(内核级别) ,它现在调用 yield
(我推测是一个系统调用)。
调度程序现在必须将当前线程的上下文保存在 TCB 中(存储在内核的某个地方) ,并选择另一个线程来运行并加载其上下文,然后跳转到其 CS:EIP
。
为了缩小范围,我正在开发运行在 x86架构之上的 Linux。现在,我想进入细节:
首先,我们有一个系统调用:
1) yield
的包装函式将把系统调用参数推送到堆栈上。推送返回地址并引发一个中断,同时将系统调用号码推送到某个寄存器上(比如 EAX
)。
2)中断将 CPU 模式从用户切换到内核,并跳转到中断向量表,然后跳转到内核中的实际系统调用。
3)我想调度程序现在被调用,现在它必须保存 TCB 中的当前状态。这就是我的困境。因为,调度程序将使用内核堆栈而不是用户堆栈来执行它的操作(这意味着必须更改 SS
和 SP
) ,它如何在不修改进程中任何寄存器的情况下存储用户的状态。我在论坛上读到,有特殊的硬件指令保存状态,但然后如何调度程序访问它们,谁运行这些指令,什么时候?
4)调度器现在将状态存储到 TCB 中并加载另一个 TCB。
5)当调度程序运行原始线程时,控制返回到清除堆栈的包装函式,线程继续运行。
附带问题: 调度程序是否作为只能运行内核代码的线程(即只能运行内核代码的线程)运行?每个内核线程或每个进程是否有单独的内核堆栈?