0%

从公众号文章中看到这次rust OS 夏令营活动, 抱着开阔眼界, 多认识同行的目的, 于是报名参加了。

第一阶段是学习rust 基本语法, 作业是使用rustlings 做110 道题。

我是两年前学习的rust 语言, 这两年也基本上在用rust 做项目,语言基础这块还是比较有信心的。但是做这些题也并没有像砍瓜切菜般,刷刷刷的一晚上搞定,花了两晚上做完100道基础题,又花了两晚上昨晚10道算法题。

主要的原因呢,是这些题目是很全面的,除了future async await 之外,关于rust 的各个方面都涉及到了。
比如 unsafe, 我可以说,写项目快两年,我没有写过一行unsafe,做题的过程也全面复习了一下rust 语言,这也算收获之一吧。

类似的, 我比较少用的方面包括, 自己实现trait, 自己实现macro,

记录一下我遇到的一些比较有趣的问题,或许对新学者有点帮助。很多是群里大家讨论的问题。

statge one, rustlings

重点和非重点(对初学者,应用层)

我学习用到的书是 << programming rust >>,现在有第二版了。

全部基于个人感受,和项目中使用的频率。非重点不代表不重要,只是说,如果你做的项目是偏向应用层的,这些内容需要理解,但很少会自己实现。如果是底层相关的,或者开发rust 库,这些可能会是重点,且常用。

重点:
+ 枚举和表达式, 我常常复习的章节, 真的很常用
+ 迭代器,不用迭代器也能实现各种各样的功能, 但是这样的C/C++ 风格不推荐。迭代器真的很有用,也很好用
+ 闭包,可能很多人第一感觉是很少会用到,但是出人意料的是,闭包还算比较常用。像迭代器一样,rust 推荐使用闭包,对闭包也有专门的性能优化
+ 错误处理,这个是rust 不同与其他很多语言的一个地方,也是很多人不理解的地方。初步处理时可以不用像库作者一样严格,结合枚举和闭包,也可以妥善处理。进阶的处理办法,需要稍微研究一下anyhow 和 thiserror 库。不要 unwrap 了之(重要的话手动乘以三遍)
+ 所有权和生命周期,老生长谈的重点,我就不说了,理解就好

非重点:
+ macro, macro 属于高级技巧, 应用层代码基本不会有自己手写macro 的需求,最多会用别人写好的。对于web 框架这种情形,很多人更喜欢函数实现的库,而非宏实现的库。对于有些不得不使用宏的场景,如DSL,再去学习研究就好了,早期没必要在这儿花很多时间
+ unsafe, 对于写OS 这种场景,unsafe 属于是必备技能了,但是对于普通的应用层,基本用不到。
+ 操作符重载, 知道就好了, 反正我没碰到过一次需要我手写操作符重载的

Copy and Clone

这个问题是群里大家讨论的时候提到的。Copy 是所有权转移的一种例外,实现Copy trait的类型, 赋值和传参数时, 会隐式复制。
参考 << programming rust >> page 71, 4.3 章节, page 236, 13.4 章节。
只说结论, Copy trait 是一种标记特型, 从代码上看 Clone trait 是其父特型,但是这并不意味着需要调用copy 方法的地方,
内部在调用clone 方法。copy 使用的仍然是内存中的按位复制方法。这两个特型之间的关系应该是一种逻辑关系,即可copy 的对象一定都是可clone 的。

unwrap ?

初学者(包括我)都会简单粗暴的使用unwrap,但是写了足够多项目代码之后,才终于明白了unwrap 是啥,到底应该怎么用。
我是在经历过上线的程序突然挂掉,集成第三方库总是莫名其妙的报错之后, debug 到怀疑人生之后, 才终于意识到这个问题的。
+ 结论就是,不要用unwrap, 除非你已经检查过了,能够完全确定这个unwrap 不会报错,然后让你的程序直接挂在这儿。
unwrap 是程序员对rust 程序的一种承诺,我已经检查过了,程序你就大胆的往下执行吧,出错了我也不会怪编译器,不会去问rust 不是号称现代,安全的编程语言吗,为啥会莫名奇妙挂掉了。
初学者往往会滥用unwrap, 在不知道自己已经做出了上述这些承诺的情况下。
函数中如果使用了unwrap, 会有一个标记trait, 标记此函数为非 Infallible, 这样在集成某些第三方库时,由于第三方库接口要求,而导致我们实现的函数不满足第三方trait 的要求,从而导致编译失败。
解决unwrap 滥用的一种常用办法是,使用watch, ? 或map_err 等方法,处理掉每一个 Result/Option 类型。

match expresion too deep nested

使用match 处理 Result 和 Option 类型是常见的操作,但是问题在于这种处理多嵌套了一层,
一不小心就会陷入多重分类讨论,层层嵌套的问题,看不清代码逻辑主干。下面是我应对的一种办法:
  • 一种方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // algorithm4.rs
    fn search(&self, value: T) -> bool {
    match &self.value {
    x if *x == value => { return true; },
    x if *x > value => {
    match &self.left {
    None => false,
    Some(left) => {
    left.search(value)
    }
    }
    },
    x => {
    match &self.right {
    None => false,
    Some(right) => {
    right.search(value)
    }
    }
    }
    }
    }
  • 另一种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
// algorithm4.rs
fn search(&self, value: T) -> bool {
match (&self.value, &self.left, &self.right) {
(root_val, _, _) if *root_val == value => { true },
(root_val, Some(left), _) if value < *root_val => {
left.search(value)
},
(root_val, _, Some(right)) if *root_val < value => {
right.search(value)
},
(_,_,_) => false
}
}

久仰Rust大名, 听说有这么一门语言要撼动C语言的地位, 很难不让人感兴趣. 后面机缘巧合, 研究的课题也与Rust相关, 因此之前就”速成”过Rust. 不过, 毕竟是速成的, 根基不稳… 在公众号里发现了开源操作系统训练营这个活动, 火速加入🤩

原本以为, 之前学过Rust, 也用Rust写过一些玩具项目, 虽然不是啥大佬, 但做Rustlings还不是手到擒来. 然后一个下午就酱紫搭了进去🤡, 不过嘛, 还是收获满满的, 补漏了很多之前不熟悉的概念, 重要的知识点也巩固了许多.

想必没人看我的学习笔记, 所以不妨在此狠狠安利这个活动😏自从加了活动的群, 就不断地被热情的社牛群U震惊, 可以在凌晨两点欢快地讨论, 可以直接和负责上课的老师交流, 可以谈天说地, 还可以欣赏各位大佬编程时花里胡哨的二次元背景🥰当然最重要的是, 真的可以学到东西. 已经在狠狠期待第二阶段的内容了!

Rust

虽然 Rust 语言非第一次接触了,但 Rustlings 是我第一次接触到这种奇妙的交互式训练模式。
通过一百多题给人带来了一个 Rust 的初步印象,后面 10 题甚至还涉及到了一些数据结构与算法。

Rustlings 巩固了我的一部分 Rust 的基础,也很好奇在后续的学习中会接触到更多的新事物。

展望

希望我能把三阶段给坚持下来,因为大佬实在太多了,我怕我坚持不下来跟不上。

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

半年前就已经听说过该训练营了,可惜错过了报名时间。

只好提前花时间为这次训练营做准备了,这次终于可以和大家一起学习,也是非常开心。

实验

rustlings里面的题目绝大部分还是挺容易的,只是涉及了一些语法。只有最后10题有难度,我有几题也是靠gpt帮忙才完成的。唉😔,怪我太菜了,还是得继续学rust啊!

总结

因为有提前学习rust,所以rustlings也是很平稳的通过了。

rustlings这个学习项目非常适合入门rust语言,给我一种很惊艳的感觉。可惜其他语言没有类似的项目, 用来入门新语言真的非常不错。

我的Rustling学习总结:

在2024年春夏季训练营中,我专注于通过Rustling项目来学习Rust编程语言,并在这个过程中获得了丰富的经验和成就:

  1. 深入理解Rust语法: 通过逐个完成Rustling项目中的练习,我深入理解了Rust语言的各种语法和特性。从简单的变量绑定到复杂的模式匹配,我对Rust的语法规则有了全面的了解。

  2. 掌握Rust生态系统: 在完成练习的过程中,我不仅熟悉了Rust的核心语言特性,还接触了一些常用的标准库和常见的编程模式。这让我对Rust的生态系统有了更清晰的认识,为将来的项目开发打下了坚实的基础。

  3. 解决问题的能力: 每个Rustling练习都是一个小问题,通过自己的努力和思考,我逐步解决了这些问题。在这个过程中,我培养了解决问题的能力,包括分析问题、查找文档、调试代码等技能。

  4. 持续学习的动力: 完成一个个Rustling练习的过程中,我不断获得成就感和满足感,这激发了我持续学习的动力。我意识到学习是一个持续的过程,而Rustling项目只是我学习之旅的起点。

  5. 扩展视野: 通过Rustling项目,我不仅学会了Rust语言本身,还接触了更广泛的编程概念和方法论。这让我对软件开发的整体流程和原则有了更清晰的认识,为我未来的职业发展提供了宝贵的经验。

下一步计划:

  • 实践项目开发: 我计划通过参与实际的Rust项目开发,将所学的知识应用到实践中,提升自己的实战经验和技能水平。
  • 深入学习领域知识: 我打算进一步深入学习Rust语言的高级特性和相关领域的知识,比如并发编程、网络编程等。
  • 持续贡献社区: 我希望能够积极参与Rust社区的活动,为社区做出自己的贡献,与其他Rust开发者分享经验和成果。

通过Rustling项目的学习,我不仅掌握了Rust编程语言的基础知识,还培养了解决问题和持续学习的能力,这将为我未来的发展和成长奠定坚实的基础。

前言

之前就从网上看到过训练营的信息,一直很想参加,今年看到报名后果断就参加了.第一次接触rust是前年跳槽来到新公司,当时我还是一名gopher,整天沉迷于go的简单和高性能,觉得写go真的好爽,入职后才知道主要是go和rust,而且rust是主要开发语言,遂转入rust的怀抱,不得不说入门rust真的蛮难的,即使现在我还是觉得自己就是个入门水平,当然,之前从go中学到的知识又不少可以类比到rust帮助自己学习,比如tokio就借鉴了很多go runtime的设计.好了,不多说了,下面是我的一阶段总结

一阶段总结

一阶段主要是rust的基础,对我自身而言实际上就是又复习了一遍rust的学习之路,由于工作语言的原因,对于rust的所有权、生命周期、Trait、async\await等机制早就被ra调教的很熟了,所以这些部分基本上下班写了写就完成了,对于剩下的cargo env、算法等部分,基本就是靠查book、chatgpt来辅助完成的,整体而言难度还可以,新手花点时间用心看book基本都能完成的,对于后续的二阶段,我还在持续学习,希望可以顺利通过二阶段!哦,对了,参加训练营之前正好又刷了一遍phil-opp的blog-os,是个不错的学习资料,有时间的可以去看看

第一阶段总结

几天前在掘金上看到 rCore-Tutorial-Book-v3 这个项目相关的文章, 顺藤摸瓜发现正在进行 2024 年春季开源操作系统训练营。在确定了训练营是使用 rust 开发且没有报名限制后,出于对 rust 的兴趣便报名了此次训练营,希望能够更进一步的掌握 rust,同时也是工作多年后学习操作系统底层知识的良好载体。

训练营大约 4 月 7 日开始,已经开始了 3 周左右,因为有一定的 rust 基础,所为了赶进度,在没有看视频的情况下,加上利用上班休息时间,花了两天的时间,完成了第一部分的任务。不过由于 rust 的熟练度不足,数据结构很多细节也遗忘了,在完成任务的过程中也遇到了一些小麻烦。

rust 相关的问题

rust 的问题主要还是熟练度的问题,包括 API 不熟练,对某些特性不够了解,例如 AsRef/AsMut/primitive pointer。这些问题在后续的 OS 相关开发中可能会成为障碍,后续需要进一步学习巩固。

数据结构的问题

数据结构的问题主要有两点:

  1. rust 写递归数据结构相当麻烦,不仅需要多层包装,还会用到裸指针和 unsafe 相关的代码,再加上所有权和生命周期等问题,更是雪上加霜。具体多麻烦可以参考Learn Rust With Entirely Too Many Linked Lists

  2. 工作多年,对数据结构本身的实现已经不够熟练了,因此重新学习一下个别数据结构。

第一阶段题目的问题

第一阶段的题目主要来源于 rustlings,某些题目不是很明确,所以刚上手的时候有点小困惑,不过这都是小问题,个人觉得堆的实现,可以改良一下。

现在的问题

现在题目的问题是直接为 Heap 实现 Iterator trait。这里的问题有两个,第一,堆这个数据结构适不适合实现迭代器,第二个,实现迭代器的方法不太好。

对于第一个问题,我个人的观点是可以,但是没必要,毕竟基本没什么场景会用到,我们主要看第二个问题。为了实现这个迭代器,只有两种方案:

  1. Heap 上直接记录迭代相关的信息,每次调用 next 方法后修改相关信息,这就导致只能在一个地方进行一次性的迭代。
  2. 直接将 next 方法实现为删除堆中元素。

我在此处采用的是第二种方案,我相信应该有相当一部分同学是和我一样的,毕竟只要通过测试就可以了。

如何改良

以下是个人的改良建议:

第一种方案,为一个数据结构实现 Iterator 的正确做法应该是为其添加一个 iter 方法,该方法返回一个 Iter 结构体,然后为 Iter 结构体实现 Iterator trait。

第二种方案,不要为堆实现 Iterator,改为直接实现 delete

下一步规划

第一阶段可以算是紧赶慢赶的顺利完成了,接下来,在正式进入第二阶段前主要会重点在以下几个方面进行学习:

  1. 学习 RISC-V 相关知识。RISC-V 是近些年的新架构,由于并非从事相关领域,对此并不了解,因此需要抓紧学习
  2. 学习操作系统相关知识。工作多年,很多东西基本已经遗忘了,需要重新了解学习一番。
  3. 学习巩固操作系统相关的 rust 语言特性。

在完成第一阶段用到的一些链接

API 文档

其他参考资料

[TOC]

前言

已是完成了第一阶段的学习了,此时作的序再称作”前言“或许有失偏颇,然而按照惯例,还是依然以前言起头罢。

Rust学习阶段

缘起

​ 我本人是区块链工程专业的学生,Rust语言本身在区块链领域已有了足够深入的应用,我也因此被学长推荐过这门语言。据他所言,他欲学习这门语言却已囿于时间不足的困境了,说是这门语言是要通过两年的学习才能入门的。然而我却欲尝试一番,却半途而废,如今才终于随着训练营的学习将其捡起来。

其路如此

​ 于我而言,学习Rust已有的历程是十分单一的,仅仅是阅读《Rust语言圣经》和练习rustlings罢了,最初是阅读英文原版,后来受限于本人十分蹩脚的英文水平,实在受不了如此低的效率,只得去阅读中文版。想来欲通过一次学习便收获两门语言,果真是困难重重吧。而rustlings对初次接触Rust语言的我来说确实也具有一定挑战性,然而收获也确实颇丰,这是仅仅通过阅读书籍而难以得到的。

明明如月,何时可掇

​ Rust语言很有意思,却也很难,到现在为止,我也不看说对其有了一个相对具体的认知和稍微熟练的运用。在参加这个训练营以前,我初次学习Rust,以半途而废告终,日常也不曾使用过,如今才终于系统地做完了rustlings,也算作为一个注脚。然而,我作为一个大方向是计算机专业的学生,过去往往局限于学校本身的培养计划,并且尚称不上足够认真,所以不光是Rust语言,操作系统于我而言更是陌生。期望在接下来的学习中,能够对这些新的知识建立起足够丰富的认知,充裕自己的学识。

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

4月7日正式开营

第一阶段:rust学习 完成rustling 时间:三周

说明:第一阶段其实没有做Daily Schedule/Record,只有在学习时写的一些笔记。

资料及学习情况

Rust基础语法主要是看Rust程序设计语言

导学阶段是操作系统课程,在开源操作系统社区导学阶段
这部分课程我没看完,另外还看了一点rCore-Tutorial-Guide

相关资料链接:

由于之前配置过环境,这次在学习前的环境配置比较简单。还试了一些新的笔记软件。

学习Rust基础语法时的学习笔记:baseNotes|1-10
advancedNotes|11-20

完成rustlings总结

rustlings中加入算法题很好,比起前面对基础语法的填空,更能体会到rust编写程序的妙用。
我觉得rust是一个很有意思的语言,当然我也感到Closure,Trait等的使用对我来说是不易掌握的。
第一阶段学完我感觉自己还是很有欠缺的,希望在之后的学习中能够真的入门。

一阶段总结

前言

其实很久之前就一直想完整的过一遍rcore,奈何时间总是不允许。这次正好在写毕业论文,就抽出一点时间。

过程

第一阶段的rustlings其实几年前就做过一次。没有太多可讲的点,但是训练营似乎增加了几道之前没接触过的数据结构题,应该属于原创内容,还是比较有趣的。几种数据结构都是比较经典的,但是由于rust语言的特性,诸如链表或是二叉树结构的节点中,子节点都使用了Box智能指针来保存。在一般的传统语言,诸如c/c++,我们会直接保存该指向结构的指针,而rust中,裸指针的操作是不安全的,所以题目中使用Box将节点结构包裹起来。
这里有一个经典入门问题,为何不在结构中直接保存同样结构的子节点而是使用指针呢?原因在于循环嵌套的结构体会导致编译器无法确定结构体的大小,而指针(当然也包括Box)是固定大小的,从而使得在循环嵌套的情况下,能让编译器在编译期确定结构体的大小。
对于指针的操作,习题中出于简单考虑,直接在unsafe中使用裸指针操作解决了,实际上,通过使用其它智能指针,合理的设计结构体,是能够完全避免使用unsafe的,这里就不展开说了。希望能够顺利完成所有训练。

二阶段总结

二阶段的内容前面和blog-os基本没什么大的区别,因为以前和洛佳一起翻译过一次,没什么太多能讲的。主要是文件系统这一块,之前没有太多了解。文件系统的结构从某种程度上来说和内存的分页机制很像。另外需要注意的是软硬链接的区别。

  • 硬链接(hard link) ln
    • UNIX文件系统提供了一种将不同文件链接至同一个文件的机制,我们称这种机制为链接。它可以使得单个程序对同一文件使用不同的名字。这样的好处是文件系统只存在一个文件的副本。系统简单地通过在目录中建立一个新的登记项来实现这种连接。该登记项具有一个新的文件名和要连接文件的inode号(inode与原文件相同)。不论一个文件有多少硬链接,在磁盘上只有一个描述它的inode,只要该文件的链接数不为0,该文件就保持存在。硬链接不能对目录建立硬链接!
    • 硬连接是直接建立在节点表上的(inode),建立硬连接指向一个文件的时候,会更新节点表上面的计数值。举个例子,一个文件被连接了两次(硬连接),这个文件的计数值是3,而无论通过3个文件名中的任何一个访问,效果都是完全一样的,但是如果删除其中任意一个,都只是把计数值减1,不会删除实际的内容的,(任何存在的文件本身就算是一个硬连接)只有计数值变成0也就是没有任何硬连接指向的时候才会真实的删除内容。
  • 软链接(symbolic link) ln-s
    • 我们把符号链接称为软链接,它是指向另一个文件的特殊文件,这种文件的数据部分仅包含它所要链接文件的路径名。软链接是为了克服硬链接的不足而引入的,软链接不直接使用inode号作为文件指针,而是使用文件路径名作为指针(软链接:文件名 + 数据部分–>目标文件的路径名)。软件有自己的inode,并在磁盘上有一小片空间存放路径名。因此,软链接能够跨文件系统,也可以和目录链接!其二,软链接可以对一个不存在的文件名进行链接,但直到这个名字对应的文件被创建后,才能打开其链接。
      关于最后一章的死锁检测,由于具体的算法已经给出,实际上只要在每次上锁解锁的时候进行一些处理即可。

总的来说,rcore的文档可以说非常丰富,可以学到很多,但就实验来说,其实和文档脱节比较厉害。同时如果只是为了完成实验实际上并不需要对rcore了解太多,等之后有空看看mit6.s081是怎么做的,是否在实验编排上有所区别。