0%

2024一阶段总结

由于我在暑假期间花了十几天时间学习了一下Rust,所以在这一阶段期间我就是相当于直接做题了,没什么可说的。但是,第一阶段也是Rust学习阶段,那么这样来说,这一阶段也就不仅仅是那三个星期,还包括了暑假期间的学习。所以,我就把这一阶段的总结写在这里。

Read more »

第二阶段开始从零开始构建操作系统的各个模块,不断完善操作系统核心功能,这一阶段,我首先从裸机开始实现了一个简化的内核启动程序,学习到了从了裸机开发OS的基本思路,后面随着每章的习题练习,不断学习了进程管理、内存管理、文件系统、并发等操作系统必备的各个子系统的基本原理。

第一个实验是实现sys_task_info系统调用,这个系统调用用于获取任务的一些基本信息,包含任务状态、使用的系统调用次数以及任务运行的时间,通过这个系统调用的实现我学习到了任务的基本实现原理及任务调度的基本原理。

第二个实验是实现 mmap 和 munmap 两个系统调用,首先将传入的参数转换成VirtAddr结构, mmap中, 获取当前进程task, 通过调用 task 中 memory_set.insert_framed_area 进行映射并插入到 memory_set 中; munmap中, 同样 获取当前进程的task, 然后获取task的memory_set检查内存区域是否合法, 最后在调用 memory_set.umap接触映射。这个实现我学习到了内存管理实现的基本原理。

第三个实验是实现 spawn 系统调用和stride 调度算法。spawn 实现了fork+exec,根据进程名解析elf,使用TaskControlBlock::new创建进程,加入到任务队列中,即完成了进程的创建及执行。stride 实现了任务根据优先级进行简单调度算法,通过优先级计算pass,P.pass = BigStride / P.priority 进程每次调度进行累加,每次调度根据stride,找到最小的进行调度。通过这个实验也算是自己实现了一个任务调度算法,感觉还是比较神奇的。

第四个实验是实现了三个系统调用 sys_linkat、sys_unlinkat、sys_stat,这三个系统调用都是和文件相关的,我实现的比较粗暴,link实现根据源文件,创建DirEntry跟原来的文件名不同,其他相同,unlink根据文件名删除Direntry, stat实现为每一个File示例实现stat函数,或许在细致实现一下可以增加一些字段来进行必要的记录,以避免每次都遍历root node。这个实验算是文件系统的小时牛刀,对于理解文件系统的原理十分有帮助。

第五个实验实现了是否开启死锁检查系统调用enable_deadlock_detect及死锁检查的算法。enable_deadlock_detect实现是为每个进程增加一个标记enable_dld来控制是否开启死锁检测,死锁检测算法是按照题目中给出的算法描述严格实现的,其实实际上可以简化很多,例如如果将锁比作临界资源,一个进程一次获取锁只相当于获取了数量为1的资源,是不可能同时占有多于1个 临界资源的。

在逐步构建和完善操作系统的过程中,我深入理解操作系统的内部机制,并逐步实现从基础功能到复杂功能的过渡。

rcore秋季训练营总结

在 RCore 夏令营第二阶段,我收获颇丰,对 Rust 语言与操作系统有了更为深入的理解。在 Rust 语言学习方面,我全面掌握了其独特的所有权、借用和生命周期规则,这些特性构成了 Rust 保障内存安全的坚固防线。对于操作系统,我不再是浅尝辄止。从内核架构层面,清晰地理解了从启动到各个模块交互的过程,特别是在进程管理中,明白了进程的创建、销毁以及状态转换原理,以及不同调度算法对 CPU 资源分配的影响。在内存管理领域,深入研究了从物理内存分配到虚拟内存映射的机制,页表机制作为连接二者的关键,让我惊叹于内存管理的复杂性和精妙性。在实现小型系统组件的个人项目中,我将 Rust 与操作系统知识融合,经历了从设计、实现到调试的完整流程,在解决诸多难题中实现了自我提升。这一阶段的学习为我打开了新世界的大门,未来我将持续探索,把所学更好地应用于实践。

Rust之路

与Rust的邂逅,应该是大概2020年的某个白天,在TIOBE编程语言排行榜中突然看到了一个陌生的语言Rust。它的名字引起了我的好奇心,这个语言的出现,似乎暗示着某种新趋势,毕竟在那个时候,Python、Java和C这些传统大牌仍然占据着榜单的前列。

我当时并没有立刻去深入了解它,而是简单地在网上搜了一些资料。初步了解之后,我发现Rust似乎是一门致力于解决内存安全和并发问题的系统级语言,它通过所有权、借用和生命周期的概念,确保了内存的管理比C/C++更加安全,却又不牺牲性能。这个点吸引了我,因为作为一名从事系统开发的工程师,我深知内存安全问题的复杂性和严重性。

随着时间的推移,我开始在工作中接触到更多关于Rust的讨论,特别是在一些性能优化和系统底层开发的项目中。于是,我决定亲自试试Rust,看看它是否真如资料中所说的那样,能在保持高性能的同时,还能提供更高的安全性。

刚开始学习Rust时,我对它的独特设计感到既惊讶又困惑。尤其是Rust的所有权模型,它要求程序员明确控制内存的使用,这与我之前接触过的语言截然不同。比如,在Rust中,每个值都有一个所有者,并且只能有一个所有者,这样就避免了传统语言中的内存泄漏和悬垂指针等问题。起初我觉得这些概念过于复杂。每当编译器抛出错误,我常常需要花费大量时间去解读错误信息,理解这些错误背后的内存模型。

后面学习了几个rust视频,前后入门了好多回,才算弄懂了rust中一些基本的概念。学习过的视频里边最值得学习的当属Rust编程语言入门教程,这个视频的作者是微软的MVP开发者,讲解rust思路非常清晰,从不拖泥带水,并且视频做了后期处理,应该跳过的地方做了加速处理。

2024年初,通过rust中文社区微信公众号得知了opencamp训练营,由于所从事的行业跟操作系统打交道比较多,自己有比较喜欢rust,于是参加了cicv第一届中期训练营,这次也是抱着试试的心态,因为之前的初级训练营都没有参加,自从这次训练,通过rustlings的练习及课程中老师们对rust的讲解,以及最后的实践项目,rust进步了很多。

这次秋冬季开源操作系统训练营,很早之前就预览了往期的一些课程,看了往期的课程更是喜欢不已,很早就盯着开课的日程,终于在开课的第一时间就参加报名了,课上除了巩固了rust的很多基本知识,也学习到了一些新的有趣的特性,随着学习的不断进行突然又觉得自己只是学了个皮毛,rust还有大量的内容需要去摸索去学习。

总结起来,我与Rust的邂逅虽充满曲折,但最终成就了我作为开发者的一次重要转变。Rust教会了我如何更加精细地思考代码的内存管理和并发处理,如何通过语言本身的设计,去实现更高效、更安全的系统编程。在这段学习旅程中,我深深感受到它带给我的不仅是技术上的提升,更是思维方式的转变。

Rust学习资源

crates.io
docs
Rust Language Cheat Sheet
rust std
The Rust Programming Language
Rust 程序设计语言 简体中文版
Rust By Example
通过例子学 Rust
exercisms.io 快速练习
Learn Rust With Entirely Too Many Linked Lists
leetcode for rust
Command line utilities
Rust标准库分析 inside-rust-std-library
Rust Playground
rustexplorer
Rust编程语言入门教程

Rust个人小项目

基于wasm的四六级英语学习项目
vnc的rust接口封装项目
kubevirt客户端工具
虚拟机加压工具

第一阶段

这一阶段没啥好说的,之前已经参加过好几次训练营了,rustlings 也不知道是三刷还是四刷来着,总之还是很顺利的

第二阶段

这次第二阶段相较上一次进步就很大了(上次只做了lab1),总体而言感觉收获还是很大的

对我而言,最难的是lab2和lab4,光看文档是真不懂,还是得 RFSC

在理解页表分配的时候,一定要根据link.ld画内存图帮助理解,不然真的会绕晕,之前在学习操作系统的时候只知道有这么个机制,真到实现起来的时候才发现这么复杂,有些认为想当然的功能都要通过很复杂的调度

lab4代码很多,但是写起来是有技巧的,当我看到文档上说到“松耦合”的时候,就提醒了我一点:既然已经做好了解耦的工作,那也就意味着我在编写内核的时候其实是应该不需要太关心文件系统的具体实现的,只要调用固定的几个API应该就能完成任务。

果然,在逐个观察几个相关的系统调用的实现之后,我找到了几个关键的API,还算轻松地完成了任务

写lab5的时候有点被群里的人带偏了,还以为要实现银行家算法,清醒过来之后才发现是死锁检测

开源操作系统训练营第二阶段总结

学习契机

之前有断断续续看过一些课程,没有加入到学习训练营中,自己一个人没有啥动力。这次通过其他其群的信息,加入训练营和大家一起开始学习,一起探讨,最终完成了所有课程的学习,并完成了题目练习。

学习内容

  • 了解操作系统的基本概念和发展历史
  • 了解操作系统的基本原理和设计思想
  • 学习了操作系统的一些基本概念,如文件系统、进程、线程、调度、死锁、互斥、信号量、管道等。

学习心得

和大家一起学习,更加容易坚持到最后。学习中遇到的问题,也可以及时和群友讨论。因为需要完成题目拿分数,有时候会功利性比较强,以完成测试为目的,忽略掉一些知识点。最后学完之后可能容易忘记,可能需要多多复习。

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

学习

  • 学习了rustlings的课程,并完成了所有练习。

心得

  • 学习之前主要还是需要看完官网推荐的书籍,然后再去学习和练习。
  • 练习过程中,可以边做边学,遇到问题可以及时查阅文档和群友进行讨论,避免陷入牛角尖。
  • 借助ai的帮助,可以更快的学习和掌握知识。

收获

  • 通过rustlings的练习,对rust的熟悉程度有了更深入的了解。
  • 了解使用rust来实现一些数据结构和算法。

第二阶段总结

这个阶段主要是要完成几个实验,借助几个实验理解一个具有进程/线程管理、内存管理、文件系统、进程间通信和提供了一定同步机制的内核是如何构成并运作起来的。

比较深刻的有这么几个知识点:

  • 链接脚本与全局符号的使用
  • Rust的汇编嵌入
  • 第四章中,在使用分离内核空间的时候。通过设计跳板页来解决切换页表后指令执行的问题。跳板页
  • 第六章了解了文件系统,了解了块设备的概念,对文件系统的各个抽象层有了一定的了解。
  • 第七、八章了解了操作系统是如何为应用提供同步原语的

跳板

由于我们的内核使用了分离内核空间的设置,所以在Trap的时候需要切换页表。但在切换页表之后,pc寄存器还是忠实的在其原来的位置自加到下一条指令,如果内核内存空间程序内存空间对这段代码的映射不是在同一个位置的话,则会表现出来程序跳转到了别的地方执行的效果。因此我们设计了一个跳板页,在虚存中映射到所有内存空间的最高页,确保在切换之后,也能正确运行下一条指令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# trap.S
...
.section .text.trampoline
.globl __alltraps
.globl __restore
.align 2
__alltraps:
csrrw sp, sscratch, sp
...

# linker.ld
...
stext = .;
.text : {
*(.text.entry)
. = ALIGN(4K);
strampoline = .;
*(.text.trampoline);
. = ALIGN(4K);
*(.text .text.*)
}
...

在上面的汇编可以看到,我们给trap.S分配到了.text.trampoline段,并在链接脚本中定义了一个strampline符号来标记他的位置,这样我们可以在Rust中找到这个跳板页,映射到我们期望的位置。

但将跳板也映射到别的地方带来了新的问题,原来__alltraps中最后跳转到trap_handler使用的是call trap_handler。我们可以通过obj-dump看看编译得到的指令。

1
2
3
4
5
6
7
8
9
10
# obj-dump -Dx ...

...
80201056: 73 90 02 18 csrw satp, t0
8020105a: 73 00 00 12 sfence.vma
8020105e: 97 80 00 00 auipc ra, 0x8
80201062: e7 80 e0 0b jalr 0xbe(ra) <trap_handler> # pc+0x80be
...
000000008020911c g F .text 00000000000003b2 trap_handler
...

可以看到,这里用的是pc相对寻址,也就是基于当前指令的偏移找到trap_handler所在的位置。但是现在__alltraps已经被我们映射到内存的最高页去了,也就是说我们实际运行代码的时候是在下面这一段内存中。

1
2
3
4
5
6
7
8
9
# gdb
>>> x /20i $pc-10
0xfffffffffffff054: ld sp,280(sp)
0xfffffffffffff056: csrw satp,t0
0xfffffffffffff05a: sfence.vma
=> 0xfffffffffffff05e: jr t1

>>> p /x $t1
$9 = 0x8020911c

很明显如果这里跳转到$pc+offset$的话,并不是跳到位于正常代码段的trap_handler。所以我们要将这里换成寄存器跳转,将trap_handler的地址放到寄存器t1中,这样才能顺利地调用到trap_handler

第一阶段总结

原版rustlings曾经做过,但是这次添加了一些题目,不过也曾经在exercism.org上接触过相似的
通过这110道题,完整的复习了一遍Rust的相关基础知识,特别是最后的几道很有Rust特色的数据结构题