0%

学习背景

本人是一名大二学生。

去年三月自学过 rust,使用 rust 写过两三个练习的小程序,所以对 rust 的语法和所有权机制还是比较熟悉的。且从去年年底起,对操作系统相关的知识非常感兴趣,在刷了南京大学 Jyy 老师的课后对操作系统有了大概的概念(虽然并没有做 lab)。

今年通过同学,了解到这个夏令营。居然是用 rust 来写操作系统!遂叫上两三个队友一起加入了。

程序安全

内存安全一直是程序设计中一个难以解决的问题。从原始的 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

第一阶段

这个训练营几年前就知道了,看过了好几届它的宣传,以前也进入过一次网络教室,但并没有报名。
主要是不知道这个东西是什么,和自身领域隔得很远。再加上平常写软件程序,不知道这些底层知识和算法也一样可以写代码。

今年才报名,也没什么原因,想了解就参与咯。对此没什么学习目标,能学到我想学到的东西就够了,
学到不想继续了解为止。(实话)

这阶段的任务是完成 rustlings。

花了两个多小时完成,完成了 rustlings 前 90 多道题。那些题在几年前就做过了,中途感觉在浪费时间。

第二天完成 rustling 剩余十多道题:算法题主要花在查那些算法知识上,因为平常写代码不会用到算法。

写完算法题,开始觉得没浪费时间了。

提前进入第二阶段去自学 rCore 那本书,除了熟悉的 Rust 部分,其余部分我一无所知,看得非常吃力。
不过这不属于第一阶段的总结了。仍在学习路上。

第二阶段

这阶段对我来说太过于挑战了,围绕《rCore-Tutorial-Book-v3》经历了几个过程:

  1. 作为一个非科班的 coder,我的知识体系里面没有操作系统的任何具体知识,所以第零章对我来说特别新鲜
  2. 然后,进入第一章后,我对除了 Rust 之外的几乎所有的东西都很陌生,比如指令二进制表示与各种含义。
    所以为了弄清楚它们,需要经常问 AI 和查 riscv 手册。
  3. 第二、三章:依旧是在弄清楚汇编、寄存器这些知识上狂补,总结了一些笔记发布在自己的博客上,然后
    当周问 kimi 的时候,无意发现我的博客链接被作为那个问题的参考资料之一,哈哈哈,有成就感了。
  4. 第四章开始是一个分水岭,对汇编之类的细节可以觉得不必死抠,但马上被抽象的概念绕进去了,然后我不再记
    笔记了,因为主要是理解为主,只关注“是什么、怎么做”这些重点,弄清楚内存映射的基本步骤。
  5. 随后的章节,我开始以精简版的 tutorial 为主,重点看怎么做,从代码出发,然后不能理解的地方才去看书里的解释。

花时间最多的地方是内存映射和银行家算法上:

  • 内存映射:很多概念(物理地址、虚拟地址、页表、页表项)同时出现,所以需要梳理它们,然后才能串起来理解
  • 银行家算法:第八章的编程题花了很久写,首先一开始没理解题目的算法描述,网上搜索一番之后,依然糊里糊涂的。
    然后课件中给了我一些启发,但依然没理解。尤其是,本地测例能跑通,在 CI 上又不能通过,但 CI 没报告哪个测例不通过,
    所以只能修改一点,推送给 CI。最后我在理解测例的基础上,在纸上整理思路,结合日志去思考死锁发生和没发生的情况,
    弄懂了算法描述,最后修改了几次代码,通过了。

最后,还有一些时间花在工具上:比如学习 tmux、gdb,以及 git 合并冲突上。

背景

沉迷 LOL 十年,归来仍是白银 的经常翘课但毕业后有自己复习408专业课的血亏科班老东西,写过 vue,nodejs,python,C

(欢迎找我干活,可以为爱发电)

第一阶段做的事就是 90% 刷 rustlings,加上 10% 复习了下基础知识

rust

一言以蔽之,我永远喜欢 C 🌝🌝🌝🌝🌝🌚

安全诚可贵,自由价更高。但是为了完成训练营还是学习一下

类型太多要匹配,所有权转移,可变引用与不可变引用的限制 是耽误我最长时间的,机制理解但是感觉用起来就是很不方便。

参考资料

圣经也就图一乐,真学rust还得 官方文档,写代码神器:官方手册

官方文档:理解一些机制和基础用法,做 rustlings 里模块分类和调用方式、编译器参数 等题目时用到的

官方手册:各种类型包含的函数和用法,不会做了就翻一翻,在左边列表找一找,经常能有意想不到的收获

具体内容

对我有用的新学到的且值得值得记录的 主要是 Option 的几个方法

  • as_mut() :&mut Option -> Option<&mut T>.
  • as_ref() : &Option -> Option<&T>.
  • as_deref_mut() : Option (or &mut Option) to Option<&mut T::Target>

前面题目里用到的时候只是按照提示修改,没有细究功能和用法,后面算法题才发现很好用

还有一些用起来不熟练或者还没用但感觉以后可能会有用的,具体用法等实践中再研究了

  • Rc, Arc, Cell, RefCell

数据结构

包括 rustlings 里新加入了一些算法题,小复习了一下涉及到的 BST, heap 的内容,

其他 BFS, DFS, stack,queue,图,都太基本了没啥好说的,DFS 连边的类型都不用区分 =。=
建议下次提升到 912 难度😉(bushi)
加点 最短路径、KMP啥的 可以有🥺

二叉搜索树

  • 特性:中序,任意 parent 不小于左子树,不大于右子树。
    亦即中序遍历序列单调非降

    完全二叉树

  • 平衡因子处处非负:左子树满树

  • 逻辑节点与物理元素依层次遍历次序彼此对应:

Parent(i) = ( i-1 ) >> 1
LChild(i) = ( 1 + ( i << 1 )
RChild(i) = ( 1 + i ) << 1

完全二叉堆

  • 用物理上的向量实现逻辑上的完全二叉树
  • 维持偏序而非全序,即 val [i] <= val [Parent(i)]

操作

  • 插入 + 上滤 O(lgn):只与 Parent 对比并直接互换
  • 删除 + 下滤 O(lgn):用末节点填充根节点(维持结构性)+ swap(e, max(Lchild, Rchild)) (维持堆序性)

操作系统

当年就这门课学得最好,前几个月刷了下 《Three Easy Pieces》,看一半发现还是 rCore指导书 最好,理论与实践相结合,讲解详细清晰,操作切实可行,跟着刷了两章

第一阶段用不上,剩下的等到第二阶段再补啦

第一阶段总结

关于Rustlings

  • rustlings的110道题全部完成
  • 有关rustlings中tests7和tests8中关于build脚本那块儿仍然不是很清楚
  • 其他个人感觉掌握的还行

关于Rust的学习

在第一阶段,我对RUST的学习主要参考了以下开源书目:RUST圣经,RUST程序设计语言,布朗大学的RUST教程。结合上述书目以及训练营课程的讲解可以基本搞明白RUST中的几个关键概念:所有权,生命周期等。

最后总结与展望

虽然已经顺利通过了第一阶段的学习,但是我明显感觉到我对RUST还并不是很熟悉,因此后需还需要补强对RUST的了解。同时也希望自己能坚持下来,在第二阶段和第三阶段学到更多的东西。

2024 rcore-os第一阶段 Rust基础 报告

作者:李明宇(getKongBai)

学习内容难点

Rust所有权与生命周期

Rust的所有权要求每个值只允许有一个变量拥有其所有权,引用类似于并发的读写锁,读引用可以同时存在,但是写引用不能同时存在、也不能与读引用同时存在,写独占读共享。Rust的生命周期确保引用在有效期内是有效的。

Rust智能指针

Rust的智能指针包括但不限于Box、Rc和RefCell,Box用于在堆上分配内存,Rc用于在堆上共享内存

Rust并发

Rust的所有权机制在并发时完全就可以当锁用,但也因此:通过通讯来共享内存、而不是通过共享内存来通讯。

Rust宏

学的很少,一种基于语法的元编程,需要用模式匹配解语法树

Rust链表

最折磨的一集,引用来回变化,满地的unsafe

写Rust的小技巧

少用可变变量

可变变量需要来回考虑可变引用

用函数式编程解决问题

使用函数和递归可以解决很多变量所有权问题和引用的相互冲突(尽量写纯函数)。写数据结构的时候很多代码第一开始我用循环,结果被各种引用折磨,后来用递归实现可以少考虑很多引用问题

第一阶段报告

首先感谢活动主办方给了我们学习的机会和学习的资源,感谢助教一个月来的解答疑惑和帮助建立学习环境

Read more »

背景

初次接触 Rust,是在学校学习操作系统课程的时候。这门课的练习课中,需要用 Rust 语言来完成编程练习。在学习 Rust 之前,我对编程语言的学习并没有很大的热情。因为在我的印象里除了学习第一门编程语言 C 的时候花了些功夫,之后学习的 Java,Python,Javascript 之类的都是熟悉一下语法后就很快上手。当时我看学校里课程的安排也就是大概给学习 Rust 一周的时间,后面就开始做各种练习了,所以我并没从 Rust 这门语言中期待过什么特别复杂的东西。

真正开始学习的时候,发现事情好像并没有我想的那么简单。我发现除了要理解 Rust 的生命周期,所有权等概念意外,还要关注很多底层的细节。慢慢地我就明白了,想要真正理解 Rust 这门语言,我需要深入思考 Rust 的设计哲学,多看看 The Rust RFC Book,收获会非常大。

对于 Rust 这门编程语言的学习,离我最开始接触有一段时间了。这次训练营的第一阶段,其实对我个人来说是对这门编程语言的复习和巩固。

心得体会

学习 Rust 我感觉没有很难,多读一读 The Rust Programming Language, The Rust RFC Book 和 标准库文档,对于初期学习完全足够。对于 Rustlings,我并不是特别喜欢,对于学习来说帮助并不大,里面的练习对于学习者来说就是难者不会,会者不难。多写多练多交流,有疑惑不要迟疑,打开 Rust Playground多写示例探索,在我看来是最好的学习方法。

对于语言本身那些细碎的知识点,也没做过详细的笔记。也就是在学习闭包的时候写过一篇总结:Rust中的闭包与关键字move

参加这次训练营也是想重新拾起 Rust,并将其运用到实践当中。

背景

我对rust很有兴趣,是通过rust社区来到此训练营,对我而言理解编译原则过于困难,停留在看简单看点语法的阶段,在实践中遇到很多困难。希望经过训练营学习后第一可以熟练使用rust语言开发。然后可以认识更多的伙伴去探讨os相关的架构和知识。

过程

在第一阶段训练中,确实让我感到惊艳,每想到rust还有那么多的技巧,方便的训练工具让我巩固了基本的知识。
主要感受体现在:
1. build.rs 之前编程中很少考虑到,训练中保存就会自动检查,确实减少了很多焦虑;
2. 在尝试完成 test.7 时各种摸不到头脑,也是查了很久才知道cargo还可以加`:`增加编译参数;
3. 对使用 unsafe 过于恐惧,感觉失去编译器的说明总觉得会出问题,当然在算法一中也是尝试了好久才完成,不是很理解但是也得到了锻炼的机会,不至于感到害怕; 

结论

虽然在我答题的过程有些草率也碰到了一些unsafe知识的困惑,但是也在完成训练的过程中提升了对基础语法的理解,也提升了我对使用rust的信心。
在群里的氛围也是很好,讨论了一些知识,也分享了很多学习资料,相信经过完整的训练,定会有收获。