进程切换时是如何保存上下文的
前言
当前操作系统大部分采用分时的进程调度, 既每个进程运行一小段时间, 然后切换到下一个进程运行, 依次往复.
当进程运行的时候是独占CPU
的, 此时操作系统是无法强行介入的, 为了将执行权让出来, 就需要硬件的配合了. 硬件每个一个时钟周期(比如10ms), 就会产生一个时钟中断, 而这个时钟中断会将执行权强行交给操作系统的调度进程, 然后由调度进程进行后续处理.
以上, 就是我在第一遍看操作系统时留下的印象, 但有几个问题当时没有搞明白:
- 如何保存进程的上下文? 在将进程暂停后, 为了之后再次运行, 需要将运行现场保存起来, 以便再次运行时恢复. 而在
CPU
的角度, 运行现场其实就是几个寄存器的值. 想标志寄存器/通用寄存器/段寄存器等等, 调度进程都能拿到, 我都能理解. 但是, 指令寄存器PC
如何保存呢? 当执行权交给调度进程后,PC
自然也就指向了调度进程, 已经丢失了当时的值. - 若在调度进程运行时, 再次发生了时钟中断, 不就陷入死循环了.
以上问题, 在多年后我再次重翻操作系统时, 得到了解答.
解惑
如何保存上下文
其实, 前面的分析是没错的, 当执行进程切换后, 指令寄存器的值必然指向当前执行的进程. 既然软件办不到, 那就硬件来做咯.
找到了这样一篇CPU文档 (可能和现在主流 CPU 实现有所差异, 不过作为参考倒是问题不大):
![image-20220522122614103](https://oss-blog.cdn.hujingnb.com/img/202205221226518.png)
当触发中断时, 会将PC, X, A, CC
寄存器的值保存到栈中. 其中X
A
是通用寄存器, CC
是一个条件码寄存器, 在文档的5.1
小节对这些寄存器均有介绍.
哎, 这不就解决了切换后的上下文问题么.
中断嵌套问题
当调度程序正在运行时, 再次发生中断怎么办? 如果能将中断关闭, 不就没人来打扰了么.
没错, 就是这么干. 通过修改CC
寄存器的值, 可以达到关闭中断的效果.
![image-20220522124633656](https://oss-blog.cdn.hujingnb.com/img/202205221246703.png)
同时也提供了中断操作的汇编指令.
![image-20220522125215878](https://oss-blog.cdn.hujingnb.com/img/202205221252920.png)
至此, 中断的嵌套问题便解决了.
并且中断程序结束后, 调用IRET
退出, 可恢复程序执行. 这自然是为了键盘输入这种中断使用的.
总结
在看了这么一份硬件文档后, 硬件真的是做了很多事情, 很多软件做不到的事情, 硬件来做, 软件做的慢的事情, 硬件来做.
当然, 文档中不止有这些内容,, 奈何我才疏学浅, 看英文文档着实费尽. 罢了罢了, 解了心中疑惑便好...