概述
虚拟化 CPU的概念:操作系统需要以某种方式让许多任务共享物理CPU,让它们看起来像是同时运行。
在本节需要解决的关键问题是:如何高效、可控地虚拟化 CPU?
解决方法:采用受限直接执行(Limited Direct Execution, LDE)机制
直接执行的概念
直接执行:直接在CPU上运行程序即可。使用正常的调用(call)跳转到用户程序的main(),用户程序结束后返回内核。
直接执行存在的问题
优点:快速。该程序直接在硬件 CPU 上运行,因此执行速度与预期的 一样快。
存在的问题:不可控(对用户程序没有限制,且不能切换进程(时分共享))
- 对用户程序没有限制(用户程序可能做出危害行为)
- 不能切换进程(即没有完成时分共享的目标)
问题1: 受限制的操作
硬件通过提供不同的执行模式来协助操作系统。
- 用户模式(user mode)。在用户模式下运行的代码会受到限制,应用程序不能完全访问硬件资源。例如,I/O请求等。
- 内核模式(kernel mode):操作系统(或内核)就以这种模式运行。 在此模式下,运行的代码可以做它喜欢的事,包括特权操作,如发出 I/O 请求和执行所有类 型的受限指令。
系统调用:即用户程序向内核请求服务,比如读一个文件(read)、创建新进程(fork),加载新程序(execve)等。通过系统调用可以实现用户程序受限制的操作。
如果一个进程正在用户态中运行一个用户程序,并且需要一个系统服务,比如从一个文件读数据,那么它就必须执行一个陷阱或系统调用指令,将控制转移到操作系统。(即从用户模式切换到内核模式)操作系统接着通过参数检查,找出所需要的调用进程。然后,它执行系统调用,并把控制返回给在系统调用后面跟随着的指令。(即从内核模式切换到用户模式)
系统调用通过如下指令进行模式切换:
**陷入(trap)**:用户模式->内核模式
**从陷阱返回(return-from-trap)**:内核模式->用户模式
这两条指令类似于过程调用中的call,ret,但又有所不同:
- 系统调用切换到内核态。而过程调用指令并不改变模式。
- 过程调用给定过程所在的相对或绝对地址,TRAP指令不能跳转到任意地址上。根据机器的体系结构,或者跳转到一个单固定地址上,或者指令中有一8位长的字段,它给定了内存中一张表格的索引(陷阱表),这张表格中含有跳转地址。
问题2: 进程切换
协作模式
协作(cooperative)模式:操作系统相信系统的进程会合理运行。OS 通过等待系统调用(显式的 yield 系统调用),或某种非法操作发生,从而重新获得 CPU 的控制权。
代表:早期版本的 Macintosh 操作系统或旧的 Xerox Alto 系统。
缺点:过于被动
非协作模式
时钟中断(timer interrupt):时钟设备可以编程为每隔几毫秒产生一次中断。产生中断时,当前正在运行的进程停止,操作系统中预先配置的中断处理程序(interrupt handler)会运行。此时,操作系统重新获得 CPU 的控制权,通过运行调度程序来做出是否切换进程。
一些小问题
保存和恢复上下文
为了保存当前正在运行的进程的上下文,操作系统会执行一些底层汇编代码,来保存通用寄存器、程序计数器,以及当前正在运行的进程的内核栈指针,然后恢复寄存器、程序计数器,并切换内核栈,供即将运行的进程使用。
|
|
并发
在中断或陷阱处理过程发生另一个中断?
简单的解决办法:关中断,即在中断处理期间禁止中断。
reference
[1]操作系统导论(ostep)
[2]现代操作系统
[3]深入理解计算机系统(csapp)