首先感谢各位老师以及同学提供的如此丰富的Rust与操作系统相关的学习资料,令本人受益匪浅,下面是本次训练营的总结报告。
2023秋-训练营阶段总结-OneMore14
阶段一 rustlings
因为之前有一点 Rust 基础,直接做 Rustlings 没有太大问题,加上当时比较忙着工作和找租房的事,所以阶段一比较潦草,把题目做完就没有再花时间深究其中一些不熟悉的部分。总的来说,Rustings 确实是非常好的入门学习资料,重做一遍也相当于复习了。
阶段二 rCore
阶段二最开始看2023A的文档,但是感觉讲得有点模糊,后来读到详细的V3文档感觉一下子通顺了很多。虽然要读的内容多一点,但实际可能因为理解更清晰而做的更快一些。
前三章主要讲操作系统内核是如何启动的,以及启动后如何运行用户程序的。其实一切都没有魔法,无非是如何合理运用硬件规则而已。一般来说是硬件决定了第一条指令的起始位置,硬件决定如何输入输出,硬件也提供了分等级的环境让我们可以隔离用户态和内核态…总之,程序的运行最终都是落实在硬件之上的,因此操作系统需要根据硬件功能做出相应的适配。而为了简化这种适配的复杂度,又引出了位于硬件和内核之间的一层抽象,称为SBI。我们可以把SBI简单想象成”内核的操作系统”,通过SBI简化后的接口可以调用硬件某些复杂的功能,比如输入输出。在了解了裸机的基本运行环境后,再看内核其实和我们日常编写的应用软件是非常类似的,只是在某些时候,往往需要使用汇编语言来构造一些更底层的上下文或完成指令跳转。在熟悉这些技巧后,前三章内核的执行过程就比较好懂了。
第四章引入了地址空间的概念,这里再次体现硬件对内核的支持,硬件可以通过设置来开启MMU功能,直接实现了地址转换功能,甚至还提供 TLB 用作缓存。因此内核只需要考虑对内存的管理功能,而不需要在用户程序运行中转换每一个虚拟地址。在rCore的学习中,比较容易迷糊的是到底哪些空间包含了哪些部分,可以通过打印日志的访问查看堆栈的起止位置,感受程序的内存布局。
第五章引入进程的概念,其实更像是第三章的加强版。理解程序执行需要准备哪些上下文,申请哪些资源,程序进入/退出内核需要如何保存/恢复上下文,之后再做实验就不会迷茫。有点被卡住的是一开始不太理解 idle_task_cx 的作用,仔细阅读 __switch 函数才发现 idle_task_cx 保存了run_tasks() 里循环的上下文。阅读汇编代码实际含义确实不如普通代码好懂,这可能也是操作系统的难点之一吧。
第六章引入文件的实现,由于不需要关注硬件细节,最底层只需要调用实现了 BlockDevice trait的块设备结构体即可,总体比较好懂。且rCore是运行在单核处理器上,不需要考虑文件的共享问题,整体难度不大。
第七章进程间通信也主要是在目前内核至少实现一些方便的功能,并没有新硬件的引入。
第八章线程的引入更加细化了之前对进程的管理,而一些并发原语则是利用了硬件的原子指令的功能,才让一些共享变量能被安全访问。但是rCore没有引入多核,因此也比较好懂。
总体来说,通过这次rCore的学习,对操作系统内核的基本原理有了更直观的感受,一切都是硬件的支持和指令的跳转,同时也体会到Rust是如何应用在系统软件领域的,唯一稍有遗憾的是rCore没有引入多核,毕竟日常生活工作都是使用多核CPU。但瑕不掩瑜,rCore仍是非常好的操作系统入门资料,V3文档也非常详实,在此衷心感谢各位老师和同学的付出。
目前虽然完成了规定的几个实验,但深知在框架内添加代码和自己独立实现一个迷你操作系统仍有不小的差距,还需要多多学习。
sunny_rust_rcore
#rcore学习总结报告
总述
两周学完rust,两周了解rcore操作系统对于我这个大一的学生来说过程十分艰辛,虽说没有通宵打代码,但确确实实是花了几乎所有非学习睡觉时间完成的。
这里非常非常感谢举办这个训练营的所有老师和负责人,资料准备的很全,几乎不需要再找其他资料;热心负责,经常在群里答疑,课上讲得很精炼。
lab1
在这个实验中我实现了一个TaskInfo函数,该函数可以查询某个Task的运行时间、写入次数、挂起次数、退出次数和查询info次数。
fn sys_task_info(ti: *mut TaskInfo) -> isize
我通过在TaskInner结构体中加入积累响应信息的值,并在调用这些系统函数的时候维护这些值。
ps:一开始真的没想到还可以修改源代码部分,以为只是完成函数,哭
lab2
在这个实验中我重新写了sys_get_time 和 sys_task_info函数,因为这两个函数传入的虚拟地址可能被分在了不同的页
同时我实现了mmap 和 munmap两个函数,分别让用户可以申请虚拟地址空间和取消申请虚拟空间
我在重写sys_get_time 和 sys_task_info函数的时候受讲课老师引导,学习详细白皮书的sys_write的写法,知道了如何获取到用户的实际存储内存地址
在实现mmap和munmap函数中,我先判断用户输入是否合法,然后把用户给的地址取整,按每个页申请和取消空间。
ps:用户空间由TaskInner中memory_set变量控制,不能自己新建memoryset变量!!!
lab3
在这个实验中这次我实现了spawn函数的调用,它能新建一个子进程,并执行该子进程
我参考了给出的fork函数和exec函数的实现过程,在把两者结合,实现利用fork新建子进程,再利用类exec函数启动子进程
ps:fork()+exec()≠spawn()
zHappyFish-rCore-study-record
训练营学习记录
这篇文章用来记录我在2023秋冬季开源操作系统训练营的学习过程,之所以会参加本次训练营,是因为我想进一步学习操作系统以及Rust编程语言。
第一阶段(1-2周)
本阶段的主要目的是掌握Rust编程语言,为后续学习打下基础。
第一周
在参加训练营之前,我有学习过Rust,但之后并没有做过有关Rust的项目,只用Rust刷过题,以至于之前学过的知识很快就忘了,所以我并没有马上开始做训练营的题。
本周我将环境配置好后就开始重新过一遍Rust,主要重学了Rust的所有权、借用、泛型、特征、迭代器、生命周期、智能指针、多线程、迭代器。
第二周
本周我开始完成训练营的题,题目不难,但很有针对性,基本上就是各个章节的知识点,这个过程中也学到了一些重要的知识,比如build.rs、#[no_mangle],为后续学习rCore打下基础
第二阶段(3-4周)
本阶段的学习目标是完成rCore-Tutorial中的五个实验。相比于上个阶段,本阶段的学习任务要重得多,学习难度也更大,需要花更多的时间。
第三周
我首先花了一天时间配置环境,我使用的是Docker,项目中有写好的Dockerfile能直接构建镜像,可惜由于网络问题,我总是构建失败(apt-get 下着下着就卡住了,导致无法构建成功),最后只能新建了一个Ubuntu:20.04的镜像,然后在容器中按照Dockerfile的流程将容器的环境配置好,然后提交容器保存为镜像。
配置完环境后我就开始看 rCore-Tutorial 并完成实验
rCore-Tutorial 的第一章从一个应用层的Hello World开始,一点点去掉需要操作系统支持的部分,最后构建一个能在裸机上打印Hello World的程序。
第二章构建了一个批处理系统,能够依次运行导入的程序。由于没有实现文件系统,从第二章到第五章的用户程序都是同操作系统放在一起的,通过脚本生成的汇编代码来标识应用程序的起始地址和结束地址。
这一章讲到了Risc-V的特权级切换,比较重要的就是Trap的上下文切换过程。
第三章通过时钟中断实现了分时多任务系统,比较重要的就是switch过程,切换任务时我们需要保存任务的上下文,以便下次运行时恢复。这与Trap过程是不同的,Trap是用户态与内核态之间的上下文切换,而switch是不同任务在内核态的上下文切换。
第四章实现了Risc-V的三级分页机制,这里采用双页表的实现方式,即一个任务的用户态和内核态使用不同的页表,这使得我们在Trap时还需要完成页表的切换。为了使得页表切换时程序能按正常的顺序执行,内核页表和用户页表都必须映射一段相同的地址空间,这段空间保存的代码就是Trap过程的跳板。
第五章实现了进程管理,调整了一些数据结构,将进程的执行交给各个CPU(不过这里只有一个CPU),将当前运行的进程id交给Processor结构(它是处理器的抽象),然后将进程的调度交给TaskManager。为了支持在用户态输入命令,还实现了一个简单的shell程序以及sys_read系统调用。新建进程则由sys_fork和sys_exec完成。
第四周
待续。。。。
2023开源操作系统训练营一二阶段总结
感谢老师和助教们贡献了这么好的课程,可以看到付出的努力和心血,所以我也非常重视这一次的训练营。通过这次的训练营,不仅让我在短时间内快速学习使用了Rust,并乘热打铁学习实践了我一直想掌握的OS知识。在阅读文档的时候详略有当,也给出了很多扩展性的知识和难题,不过个人水平太菜并没有深入。只经过短短两周多的学习,已经基本能在脑海中对操作系统有一个较为清晰的概念了。
2023开源操作系统训练营第二阶段总结报告-hercule-karuha.md
2023rCore训练营第二阶段总结
起因
因为不满足于学校的课程教学,想写一些稍微硬核一些的作业,在2023年5月左右的时候在国内外各大操作系统公开课中挑选了一番,最终是选择了rCore,大概有下面这些选择的理由。
- 使用rust语言,对于当时刚学了一点rust感受到其优越性的我很有吸引力。
- RISC-V架构,能减少一些x64的繁琐带来的困扰。
- 支持国内老师对于本科课程的改革。
在暑假期间自学了一番并在秋冬季的训练营中靠着多学了两个月的优势在只有两周时间学习的同学们中获得了第一名))
下面简单来说一下rCore的各个实验。
ch3
ch3的任务是实现获取taskinfo的syscall,总体来说还是比较简单的。
但是实现过程中遇到了一些问题,程序运行到最后卡住了无法结束,稍微有点棘手。(时间久远没有截图)
最后发现是由于内存出现了问题,直接使用桶计数的话内存会炸掉。
解决方法稍微有些投机取巧,由于ch3只有5个系统调用就分别映射到一个数组的0,1,2,3,4就好了
1 | match syscall_id { |
不过秋冬季看起来没有人和我遇到一样的问题,我自己重新再运行也没有什么问题,不知道当时是怎么回事。
ch4
ch4也稍微有些投机取巧了,我单独在MemorySet中添加了一个字段用来实现mmap,像是这样:
1 | pub struct MemorySet { |
阅读代码理解SV39稍稍费了一些功夫,不过收获还是挺大的。
还有重写sys_task_info和sys_get_time,选择自己实现了一个函数来进行到物理地址的转换
1 | pub fn translate_ptr(token: usize, ptr: *const T) -> *mut T |
图简单没有使用官方提供的translated_byte_buffer。
ch5
ch5感觉上还是比较简单的,好像测试用例也不是很强的样子,听说有人没有实现都能过,不过应该会在线上测试被拦下来吧。
ch6
感觉按部就班地调用框架提供的函数就行,不算很难。
ch8
据选择做xv6的小伙伴说这是和xv6差别最大的而一个实验,确实也让我稍微费了一番功夫。
回头去看自己写的代码真是又臭又长啊……….
ch8的作业是实现银行家算法,在lock和unlock之前判断是否会造成死锁。
值得一提的点大概就是sys_semaphore_create函数只会在主线程中调用,因为银行家算法需要提前获知线程总的资源申请量,我的实现里面单独处理了线程id为0的情况,其他的还是比较简单的,就是几个向量加加减减的问题。
调试
使用gdb调试貌似很麻烦,源代码貌似不能很好地同步显示,不过也不怎么影响做完,用打log的方式解决了。
但是这让我的代码里面多了很多类似这样的东西:
1 | debug!( |
显得很臃肿。不过能解决问题就好。
总体感受
rCore教程的叙事方式很有意思,从历史的角度来添加一个一个模块,看书的同时阅读源代码好像自己真的是当时的操作系统开发者,面对着一个一个的问题,提出各种解决方案。难度的曲线也比较平缓,作为一本操作系统入门的教材来说是非常非常优秀的。
缺点大概就是有点过于简单了(bushi)。在看ch5的时候还试着去看了一下rcore中关于多核的部分不过因为资料太少也搁置了(摸了)。
rcore的竞品(不知道这个词合适不合适),chcore有关于多核的部分,如果有同学看到这里并对多核感兴趣可以去看看。(虽然我摸了)。
感谢清华的老师和助教为中国计算机本科教学做出的贡献。国内外的计算机本科教育差距很大不过仍有老师和同学在努力弥补着。感谢他们做出的努力。(什么时候我们学校能引进啊)
资源整理
外链资源
周报2023-02
2023-02 OS小组的会议纪要
编译Linux内核开启Rust语言支持
2022开源操作系统训练营第一阶段总结-my-vegetable-has-exploded
感谢老师和助教们贡献了这么好的课程。回顾一下这段时间的学习历程,首先是感谢课程提供的良好的资源,推荐的资料阅读大有脾益,比如那本risv手册易懂又不失深刻。课程的lab结构是一点点增加模块拓展而来的,上手难度平缓,对简易操作系统实现的核心思想有了更进一步的了解。
之前上杨力祥老师的操作系统课程,杨老师给我影响最深刻的一句话是要能够把系统结构画图花出来。 在阅读文档和代码过程中,感觉能把代码结构中的类之间的关联与作用机制、结构和内存磁盘等设备的作用原理搞清楚,能在脑袋里面建立一个大致的相互作用图景,对于理解操作系统非常有益。