xv6-lab

1. xv6-摆烂-理解

大三上学期突然很想自学CS,然后在寒假学了CSAPP的大部分后开始了MIT 6.S081这个课程。用时大概两个月(2.25-4.24)从零开始自学OS到完成了除network外的所有lab,包括2020年和2021年的版本。

学这东西纯属兴趣,想体验一下科班的感觉(

学习路径

我并没有看课程视频,原因是我英语非常差。我看的是这个翻译后的版本:https://mit-public-courses-cn-translatio.gitbook.io/mit6-s081

一般就是,先根据课程要求,浏览一遍xv6 book上对应的章节及源码,然后看上面那个文档,然后再回到xv6 book当中巩固一下。

然后lab的话,前期是根据课程安排进行的。但到后面课程会开始讲一些论文,我是在那之前把所有lab给完成的。所以在写这个文章的时候,我其实还没有结束这门课程的学习。如标题所见,这只是我这两个月来对lab的回顾。我会继续后续论文的学习

lab 1 Xv6 and Unix utilities (2020/2021)

这个其实主要目的是让你安装好环境+熟悉一下xv6的代码结构。主要任务是使用xv6自带的系统调用实现一些功能,比较难的可能是 primes 那个实验,需要你使用多进程通信来完成素数筛。

我当时的想法大致是给每个进程都维护了一个要筛的素数(通过向管道写入第一个数来完成),如果当前传进来的数没办法整除当前进程所维护的素数,就交付给它的子进程处理。

lab 2 system calls (2020/2021)

这个lab就开启了你魔改内核的征程(不是)。你需要实现两个系统调用trace和sysinfo,分别追踪系统调用以及空闲内存与进程的数量。算是最简单的lab之一了,跟着Hint做就行。

lab 3 page tables (2021)

这个lab主要考察你对RISCV和xv6内页表的理解。由于时间太过遥远,我不太记得清楚其中的细节了。但总之也是一个比较简单的lab。

lab 3 page tables (2020)

其实这个才是真正的lab3(,2021年的是阉割的版本

我是到最后才完成的这个lab,原因是它真的非常难!大概耗费了我三天时间

这个lab要求我们为每个进程都额外维护一个内核页表,来简化 copyin/copyinstr 函数所需要的内核/进程页表之间的转换。

你需要为这个进程的内核页表写很多函数,例如初始化,拷贝页表等。

你还需要兼顾效率,即你需要在同一个物理地址上同时为内核页表以及进程的内核页表建立映射,而非直接拷贝物理空间。这涉及到许多细节,可能需要允许一些非法情况发生。

lab 4 traps (2020/2021)

这个lab考察你对xv6内部如何处理trap的细节,相对来说也是比较难的。通过了解xv6如何让trap机制透明来完成该lab中的alarm功能,例如保存上下文,设置pc、ra寄存器等。

另外顺带一提,在这个lab中,你实现的backtrace函数非常实用,可以直接拷贝到其它lab中,非常方便调试。

lab 5 xv6 lazy page allocation (2020)

这个lab考察你对page fault的理解。通过对特定的page fault的处理,使内核能够“按需”分配物理内存。

同时你也需要修改其它函数,让它能够允许一些非法情况的发生。

lab 6 Copy-on-Write Fork for xv6 (2020/2021)

同样考察page fault的理解。COW fork和lazy page allocation都是可以通过处理page fault来实现的功能,但是前者可能要更难一些。因为在fork之后,新进程的页表和父进程的页表指向同一块区域,因此需要对page进行计数。这个涉及到一些多线程并发的东西,例如自旋锁来维护每个page的计数的不变性。

总之也算是比较难的一个lab。

lab 7 Multithreading (2020/2021)

这个lab有点意思,它不仅考察了你对xv6进程调度的理解,还让你了解了一下 UNIX pthread 库函数的使用,来实现多线程并发以及barrier。

多线程并发编程是个老生常谈的话题,我以后大概也会花时间深入了解一下。

但是lab本身是简单的。

lab 8 lock (2020/2021)

这个lab的主要任务是改善xv6原有的对lock的粗粒度的使用。需要你给出更加细粒度的lock方案。

对于每个lock,你需要明确它所保护的不变性

之前无聊的时候写过解法:https://atri2333.github.io/2024/04/12/lock-lab/

lab 9 file system (2020/2021)

这个lab有两个任务:第一个任务是采用页表分层的思想,将inode的indirect数据block也进行分层,来大幅扩展一个文件所能支持的大小。第二个任务是实现 symlink 系统调用,创建一个新的文件类型symlink,并可以通过这个symlink来追踪其它文件或symlink。

讲真文件系统这章我学的有点仓促,感觉有些东西并没有特别懂,但是对于lab本身还是够用。

lab 10 mmap (2020/2021)

这个lab要求你实现一个阉割版的mmap系统调用,及其对应的阉割版的munmap系统调用,能让用户可以通过访问内存来同步访问文件。

算是对前面的lab的总结了,它涉及到了页表、page fault、文件系统等知识点。

杂谈

关于调试,一般来讲是推荐gdb。但是根据我亲身经历(或者acmer的破习惯),printf调试法更加有用。这可能是由于我gdb用的并不熟练,所以调试起来笨手笨脚的,不如直接打log来的方便与显然(

另外,有一些lab并不是只靠我一个人完成的,我是适当地参考了一些其它人的做法。特别是2020年的页表那个实验,我发现我的写法和网上很多人都不一样,导致就算看别人的也没办法把自己的bug调试好(

不过最终也是赶在学校的破实验课开课前把除了network的xv6 lab都过了一遍,收获挺大的,算是对os有了初步的理解。至少给我一些名词,例如进程、线程、页表等,我都能从xv6的例子中进行联想。

后面会通过这个系列深入xv6源码:https://www.youtube.com/playlist?list=PLbtzT1TYeoMhTPzyTZboW_j7TPAnjv9XB

摆烂

这几周,除了自学这个课程,感觉就没做什么了。

可能,打了一些比赛

校赛,虽然acm退役了,但是打了rk4,仅次于三位noi选手

csp,455,虽然发挥不太好

蓝桥杯,一般般吧,国赛懒得去了

天梯赛,国一,但是我比赛期间(不知晓具体规则的情况下)本能地去头文件查了api,感觉要被查作弊了

codeforces,摆烂了,不想打,只打atcoder,然后1600还没上

学了点java

感觉,学国外的公开课,收获确实挺大

做对应的lab,居然会有点网瘾的感觉

但是现在却没有当初网瘾的动力了

好在,认识了一个非常好的人

所以这几周过的也是非常有意义