Arceos 训练营总结
转眼间两个多月的训练营要进入尾声了。
还记得国庆回山东的高铁上,在刷rustlings的算法题,小根堆的实现。
从二阶段的rCore到组件化的arceos,一路下来,对OS几大部件CPU虚拟化、内存虚拟化和文件系统虚拟化有了更深刻的理解。
下面我也从这几个方面来分别做个总结。
CPU虚拟化
了解了CPU的几种特权模式,以及到OS进行系统调用进行的硬件级别(汇编指令)支持。
包括通过对时钟中断的支持,完成抢占式调度(这也解释了在用户态较难实现lock)。
在CPU眼里,没有函数、没有内存分配,有的只是指令和数据。
对于高级语言而言,一个用户态程序的最终运行,是编译器和os和CPU共同协同运作的结果。
编译器负责栈的初始化,函数上下文的处理,os负责提供硬件资源的抽象、系统调用,CPU提供特权指令。
虚拟化的目的,是为了多个程序的调度,让每个程序“独占”CPU,减少了编码的心智负担。
内存虚拟化
这里印象深刻的是分页,页表实现。硬件层面的MMU和TLB支持。
我们实现了彻底分页,内核态和用户态是两个页表。通过分页保障了安全,也方便了应用编写。
这一块也是非常复杂的点。
印象比较深刻的是三级页表的内存占用,以及mmap的实现。通过mmap可以从内核申请共享内存、或者映射文件,减少系统调用次数。这里也是默认lazy init,用到的时候通过缺页中断去真正完成映射。
通过分页PTE也很好了保护了内存安全,是否可执行。

另外一点就是内存分配算法,内存本质就是一个大的byte[],找到一个可用的(按页不按页都可以)地址,也即index返回即可。
开启分页后MMU会进行更多安全检查。比如“数据执行保护”(Data Execution Prevention, DEP)或“不可执行位”(No-eXecute, NX),CPU碰到不可执行的代码区,会触发异常。起到防注入、溢出等的保护。
文件系统虚拟化
了解了ELF文件格式,静态link,动态link,以及文件inode的底层细节。
设计一个高效的文件系统是个复杂的工程,本质根内存分配一样,要减少内部碎片、外部碎片,而磁盘访问速度远远不及内存,真是一件复杂的事情。
总结
计算机没有魔法。通过这阵子的学习,对于CPU、内存如何协同工作加深了理解。
哪些是硬件的支持,哪些是OS的抽象、编译器的辅助,有了更深刻的认识。
比如栈的处理,编译器处理函数上下文、OS初始化栈、CPU提供栈指针寄存器,共同协作完成。
这是一次很好的练习,对于从最底层看本质非常有帮助。
感谢清华大学的主办,感谢各阶段的老师们的指导!