学习背景
本人是一名大二学生。
去年三月自学过 rust,使用 rust 写过两三个练习的小程序,所以对 rust 的语法和所有权机制还是比较熟悉的。且从去年年底起,对操作系统相关的知识非常感兴趣,在刷了南京大学 Jyy 老师的课后对操作系统有了大概的概念(虽然并没有做 lab)。
今年通过同学,了解到这个夏令营。居然是用 rust 来写操作系统!遂叫上两三个队友一起加入了。
程序安全
内存安全一直是程序设计中一个难以解决的问题。从原始的 gets 溢出攻击,到最近的 xz 供应链后门事件。多少都利用了内存天生的不安全的特性。
而 rust 做的事情,是将天生不安全的代码世界,划出一部分 safe 区域。通过在编译器上的工作,保证了程序员只要在 safe 区域内编写代码,程序就可以保证内存安全。
虽然 safe rust 的表达能力有些时候并不能让人满意,并且在写代码的时候经常和编译器搏斗()。但在我看来,这实际上是把后续 debug 所需要的精力,提前到了编写代码的时候。
所有权
这个世界上的编程语言一般分为两种:有 gc 的,和没有 gc 的
在 c/c++中,macllo 或 new 一段内存在 heap 上后,需要程序员自己在不需要这段内存之后,释放这段内存。随后可以让别的代码块使用这段内存。
这样做的问题在于:
- 很多时候,程序员可能会忘记释放被分配的内存
- 也有些时候,已经被释放的内存会被程序员误操作,再次释放
于是我们有了 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