2024春夏季开源操作系统训练营第一阶段总结报告

程序安全

内存安全一直是程序设计中一个难以解决的问题。从原始的 gets 溢出攻击,到最近的 xz 供应链后门事件。多少都利用了内存天生的不安全的特性。

而 rust 做的事情,是将天生不安全的代码世界,划出一部分 safe 区域。通过在编译器上的工作,保证了程序员只要在 safe 区域内编写代码,程序就可以保证内存安全。

虽然 safe rust 的表达能力有些时候并不能让人满意,并且在写代码的时候经常和编译器搏斗()。但在我看来,这实际上是把后续 debug 所需要的精力,提前到了编写代码的时候。

所有权

这个世界上的编程语言一般分为两种:有 gc 的,和没有 gc 的

在 c/c++中,macllo 或 new 一段内存在 heap 上后,需要程序员自己在不需要这段内存之后,释放这段内存。随后可以让别的代码块使用这段内存。

这样做的问题在于:

  1. 很多时候,程序员可能会忘记释放被分配的内存
  2. 也有些时候,已经被释放的内存会被程序员误操作,再次释放

于是我们有了 gc——

在 java 这样的语言中,gc(内存回收器)会定期暂停程序的一切行为,回收当前没有被引用的对象所占用的内存。这样的语言还有 go。

这样就不需要程序员来负责内存的释放了,也就不存在多次释放和不释放的问题了。(虽然循环依赖依旧会导致内存溢出……,但这并没有那么危险)

但 gc 其实是一个比较“重”的东西,并且会定期“暂停世界”。这在互联网服务(Java/Go)的领域并不关键,但在操作系统/嵌入式这样的领域中,底层并不喜欢 gc 这样的设计。

rust 利用所有权机制,从另一个角度缓解了内存问题。之所以说是缓解,因为 rust 也没有解决内存溢出的问题。

rust 中,一个变量可以拥有一段 heap 上的内存的“所有权”。当这个变量结束其【生命周期】后,会自动调用其 drop() 方法

而变量的“所有权”可以通过函数传递,程序员可以将一个变量的所有权移交给函数内部,然后获得函数移交出来的变量的所有权。

也可以把变量借给函数,通过 mut 关键字。让函数可以在不获得所有权的前提下,访问变量的值。

在函数需要修改变量时,也可以把变量可变借用给函数。

值得一提的是,同一时间可以存在多个借用,或者一个可变借用。这在很大程度上避免了数据竞争

在多线程程序中,也可以通过 Mutex,Arc 等数据结构,进一步避免并行程序中的数据竞争

rust 哲学

不同于 c/c++,也不同于 java/go。

rust 在自动内存管理和性能之间,选择了我全都要

rust 的 std 遵守着零成本抽象,即意味着同样的功能,使用 rust 和手动编写的代码,性能上是一致的。

这也能让人更放心的使用 rust 自带的各种数据结构和功能。

操作系统

OS 在我看来,是所有软件工程的基础,也是软件工程中的软件工程。

对硬件: 操作系统只是运行在硬件上的一个程序

对软件: 操作系统为软件创造了一个虚拟的环境,让软件程序有一种自己正掌握着整个硬件的错觉。并且,操作系统为软件提供了一系列系统调用。

状态机

jyy 老师的课给我的最大的收获,是将一切程序看作一个状态机。

而操作系统也是一个状态机: 一个管理状态机的状态机。

从这个视角看待软件世界,能很大程度上避免panic(因为看到繁杂的代码中各种函数,很难不让人头疼和恐慌)

如果你想体验这种感觉,可以 git clone 一个kernel(?)

魔法师

世界上的一切都是魔法

法师只需要喊出法咒/作出动作,世界就会回应他,在现实中展现神迹。

程序员只要敲击键盘,电脑就会回应他,屏幕上显示出对应的字母。

这中间的一切都是被封装好的。就像是魔法一样。

从普通软件的视角看,他在 systemcall 时,对于该程序来说,下一个瞬间,它所在的世界,就根据其所呼唤的 systemcall 回应了它。

编写操作系统,其实就是在编制普通软件的世界。

事实上,操作系统也只是在运用硬件和sbi提供给它的魔法罢了

最后

以上是在我眼中的 rust操作系统 ,作为一个初学者,难免出现错漏和片面。

如果读者发现什么需要指正和交流的,欢迎联系我。oveln@outlook

以及OvBlog