4.4 KiB
layout | title | subtitle | date | author | cover | categories | tags |
---|---|---|---|---|---|---|---|
post | 地址空间与进程 | 提供一种异步内核对时空资源的划分方法 | 2021-05-01 | 车春池 | /assets/img/地址空间.png | 内核设计 | 异步内核 Rust 地址空间 |
传统操作系统内核里,地址空间和进程是一一对应的关系。很多情况下两者的概念杂凑在一起,不能得到很好的区分。 在飓风内核的实现中,我们尝试引入新的划分方法,区分“地址空间”和“进程”,体现出它们各自的作用,以供实现内核的核心思想。
1 地址空间
地址空间是一组地址映射关系的集合。
这里的地址映射关系是指虚拟地址到物理地址的映射关系。软件,包括 SBI 运行时,操作系统内核,用户程序,所面对的地址都属于虚拟地址,这个虚拟地址通过称为 MMU(内存管理单元)的硬件实现会以某种映射关系转换成物理地址,物理地址是访问真实存储硬件,包括高速缓存和内存,所使用的地址。而这种虚拟地址到物理地址的映射关系,是由操作系统内核所设置的。
具体到指令集层面,在 RISC-V 指令中我们可以认为一个 satp 寄存器和它对应的页表对应一个地址空间。在这个概念的基础上,切换地址空间就可以描述为“切换 satp 寄存器并刷新 TLB”。
地址空间提供安全性隔离的作用,一个地址空间内的进程不能访问另一个地址空间的数据,可能在传统操作系统概念里面起到安全性隔离作用的是进程,但我们认为不是。我们觉得是地址空间起到了安全性隔离的作用,进程不能做到这点。
RISC-V 指令集里面针对地址空间会有一些优化点,比如 sfence 指令,可以指定某个地址空间编号,达到只刷新 TLB 中特定地址空间的页表项的效果。这种优化点是否存在取决于具体的硬件实现。
地址空间编号是什么?RISC-V 指令集里面的 satp 寄存器,第 22 到第 30 位是 ASID 位,也就是地址空间编号,它唯一地标识了一个地址空间。
基于上面的思考,我们觉得地址空间这一概念是与进程分开的,在飓风内核的设计中,我们通过地址空间隔离来进行安全性隔离。
2 进程
我们认为,传统意义上的进程定义有三个组成部分:
- 与地址空间的一一对应关系
- 资源占用和释放的单位
- 共同承担错误的单位
在飓风内核的设计与实现中,我们把传统意义上的这三个特点分割开来,分别单独去思考它们。
首先对于第一个特点,进程与地址空间是一一对应的关系,我们考虑新的设计,分别是一个进程对应多个地址空间和一个地址空间对应多个进程。
对于一个进程对应多个地址空间,我们暂时还没找到应用场景,因此在飓风内核的实现中暂时不考虑这部分。
一个地址空间对应多个进程,我们想到了一些应用场景,那就是资源相关性强的两个进程放到同一个地址空间中,相互之间的数据访问会比较快,因为这时候不需要切换地址空间,比如块设备驱动和文件系统。
对于这种设计,优点是在某些特定场景,同一个进程之间的数据访问会比较快(具体快在哪里需要我们后面去尝试实现这种设计之后才能比较好地归纳),但同时牺牲了一些安全性,因为这时候不同的进程处于同一个地址空间,可以访问彼此的数据。
对于第二个特点,资源占用和释放的单位,我们暂时沿用这个设计。
举个例子:一个进程打开一个文件,那么另外的进程就不能再次打开这个文件,因为这个文件资源已经被某个进程占用了。当一个进程退出之后,需要释放这个进程占用的所有资源,然后这些资源就可以被其他的进程占用。
对于第三个特点,共同承担错误的单位,我们也会沿用这个设计。
当一个任务的运行中遇到了不可恢复的错误,该任务所在的进程需要整个退出。也就是说,对于一个不可恢复的错误,该错误发生所在的任务所在的进程需要全部退出,另外的进程不受影响,这个错误由整个进程负责而不是由单个任务负责。