0%

rCore Learning Summary 陈禹译

整体评价

我参与 rCore 训练营,是为了较深地学习、掌握 os 知识。此前,我学习了 NJU ics pa,对 riscv isa 即配套的简易版的 os 层有一定的理解,这使我能非常高效地理解 rCore 的文档内容。

我个人是比较推荐有点基础的人去阅读、完成 rCore 的。若对计算机组成原理或基本的操作系统知识不了解的话可能无法读懂前两章,导致无法理解内核代码,从而无法很好地理解后面章节的逻辑。有一定的基础之后,rCore 就会从一个比较低的起点开始慢慢构建一个功能强大的 os,稍微花点时间就能看懂全部的代码,而不存在“庞大而不可测的代码块”。此外,Rust 的 no_std 环境也特别友好,很多实用的东西(如 format、RefCell)都会提供;而且也提供了动态分配内存的需求接口,实现之后就能非常方便地使用各个智能指针和容器了,大大简化了 os 中细微逻辑的实现难度。

Rust 编译器的强大也大大改变了实验练习的“画风”,它要求我们必须在很好地理解 API 后,自己使用 unsafe 代码并保证接口是 safe 的,然后要想办法把代码组织起来,不让编译器报错。也就是说,Rust 的特性使得我们不得不深入地理解实验代码、需求才能完成练习。只要编译不报错,就离完成不远了,而且此时也往往说明我们并没有误用已有的代码。

rCore 之旅

前几章最有意思的是各个链接脚本。较好地组织链接脚本,才能不浪费空间同时正确地启动 os,而想要理解后面的章节的许多需求(如加载 app)也需要先较好地理解 boot 过程。

app 都是通过构建脚本自动生成链接脚本来加载到内核中的,这非常有意思,我称之为“交叉构建”(化用“交叉编译”)——要清晰地认识到,内核代码和用户代码是完全分离的,rCore 中依靠 user 来编译出可运行在内核上的代码,pa 则是使用 navy-app。这打破了我们平时思考的习惯。我们能在电脑上写代码、跑起来,其实是因为 windows 有能在自己上面跑的面向 windows 的编译器,它可能是自举的,也可能是用其他 os 交叉编译了一部分的。若是没写好这样的自给自足的编译器,就只能向 rCore 一样通过元编程来加载。

关于特权级切换时的上下文保护,我发起了一个讨论

第三章引入时间片相关逻辑最大的意义是引入了中断,使得 os 的状态切换更复杂,要求更好地处理上下文关系。而第三章里有 lab1,使得我更加理解了 task 的数据结构构造(此时的 task 都被较简单地、笼统地管理,每个 task 并不能很好地自己管理自己,这在第五章(lab3)得到了改善)。

第四章,设计者让每个 task 都维护一个地址空间和一个页表,两者甚至是解耦的,使用一个地址空间时要显式指定究竟使用哪个页表,这大大增强了系统的可拓展性。而物理页帧分配器的抽象也十分令人惊叹,它是让丑陋的物理地址变得简单易用的第一步。此外,我觉得此章对跳板的解释并不是特别具体,因此我也发起了一个讨论

第六章引入进程后的数据结构设计十分精妙,而配套的 lab 也“逼迫”我去理解这种设计,希望同学们也能亲自体会到。另外,我也学到了这一非常巧妙的 Rust unsafe 代码封装技巧:当原始指针作为结果时,可以将其转化为&'static mut,这样就不需要 unsafe 也能使用该数据:

1
2
3
4
5
6
7
8

fn get_current_mem_set(&self) -> &'static mut MemorySet {

    let ptr = &mut result as *mut MemorySet;

    unsafe{&mut *ptr}

}

之后的章节我也在逐步学习,to be continued…