批处理系统 (Batch System) 出现于计算资源匮乏的年代,其核心思想是: 将多个程序打包到一起输入计算机;当一个程序运行结束后,计算机会 自动 执行下一个程序
应用程序难免会出错,如果一个程序的错误导致整个操作系统都无法运行,那就太糟糕了。 保护 操作系统不受出错程序破坏的机制被称为 特权级 (Privilege) 机制, 它实现了用户态和内核态的隔离
本章在上一章的基础上,让我们的 OS 内核能以批处理的形式一次运行多个应用程序,同时利用特权级机制, 令 OS 不因出错的用户态程序而崩溃
特权级的软硬件协同设计
实现特权级机制的根本原因是应用程序运行的安全性不可充分信任。如上一章的LibOS,应用和OS紧密连接,应用出bug,可能会连累OS,导致整个系统不可用
所以,限制应用程序运行在另外一个无法破坏操作系统的受限执行环境中:
- 应用程序不能访问任意的地址空间
- 应用程序不能执行某些可能破坏计算机系统的指令
RISC-V 特权级架构
级别 | 编码 | 名称 |
0 | 00 | 用户/应用模式 (U, User/Application) |
1 | 01 | 监督模式 (S, Supervisor) |
2 | 10 | 虚拟监督模式 (H, Hypervisor) |
3 | 11 | 机器模式 (M, Machine) |
级别的数值越大,特权级越高,掌控硬件的能力越强
到目前为止,(Hypervisor, H)模式的特权规范还没完全制定好,所以本书不会涉及
M 模式软件 SEE 和 S 模式的内核之间的接口被称为 监督模式二进制接口 (Supervisor Binary Interface, SBI),而内核和 U 模式的应用程序之间的接口被称为 应用程序二进制接口 (Application Binary Interface, ABI),当然它有一个更加通俗的名字—— 系统调用 (syscall, System Call) 。而之所以叫做二进制接口,是因为它与高级编程语言的内部调用接口不同,是机器/汇编指令级的一种接口。事实上 M/S/U 三个特权级的软件可分别由不同的编程语言实现。因此只有将接口下降到机器/汇编指令级才能够满足其跨高级语言的通用性和灵活性
执行环境的另一种功能是对上层软件的执行进行监控管理。监控管理可以理解为,当上层软件执行的时候出现了一些异常或特殊情况,导致需要用到执行环境中提供的功能,因此需要暂停上层软件的执行,转而运行执行环境的代码。由于上层软件和执行环境被设计为运行在不同的特权级,这个过程也往往(而 不一定 )伴随着 CPU 的 特权级切换 。当执行环境的代码运行结束后,我们需要回到上层软件暂停的位置继续执行
用户态应用直接触发从用户态到内核态的异常的原因总体上可以分为两种:其一是用户态软件为获得内核态操作系统的服务功能而执行特殊指令;其二是在执行某条指令期间产生了错误(如执行了用户态不允许执行的指令或者其他错误)并被 CPU 检测到
复习之前知识