Markdown to HTML

AuroBreeze Blog

A tiny, fast Markdown blog for GitHub Pages.

MIT 6.S081: Operating System Engineering

Project xv6

MIT 6.S081: Operating System Engineering

Start

为什么要开始这个项目呢?说实话,我也不知道,可能当时想到,学底层真的很酷吧(不,还不是这个原因,看下面)。

当时在大一暑假的时候,成天在家里没事干,平常的事情也不是很多,就是练车,玩电脑游戏(CSGO),自己又很无聊,平常又不会去找同学聊天,出去玩什么的,平常都是自己一个人,所以自己总是喜欢在网上找些乐子,也就是喜欢接触一些新的东西,就像是之前我说的ChatGPT,什么的,因为我对游戏的兴趣也就那样,没有痴迷的地步,我对编程也有很大的兴趣,去专门找一些,新的有意思的东西。

那天,我正好看到了一个玄学的算命网站,哈哈,就是赛博算命,也就是AI算命,当时感觉蛮有意思的,我就问AI我的事业运,他倒是分析出来,我是适合做些精密的工作的,比如编程什么的,我就跟他说, 我确实是软件工程的学生,他又帮我算,说我不适合UI,你别说,我还真的是不适合UI,在大一下的适合,我想自己做个EasyQSLP的项目,就是做一个网站,这个网站的目标就是从0到1一条龙服务式的教你要学的东西,因为之前我在学编程的适合,总是找不到合适的教程,要不然就是基础的东西不好找,要不然就是深处的,进阶的知识不好找,这是个很大的痛点,所以我就在弄这个,一开始后端的东西写的差不多了,想给网站写前端,然后发现,不是自己不会,是自己根本没有任何一点美术细胞,我知道什么好看,但是你让我空想,去创造,我脑子里一篇空白,什么都没有,连最简陋的界面我脑子都生成不出来,所以我一直都是无从下手,然后那个AI就又给我算命,说我适合底层,适合无UI的设计,我一想,确实啊,底层哪有什么UI,都是终端的东西,又因为自己之前就很想试试PWN,但是一直没学过,当然我不是说要学PWN,而是对底层感兴趣,我就正好趁着AI算命的这个契机,开始自己的底层的学习。

当时正处于做完build-own-your-x上的用C/C++实现redis的项目的结尾,我就问其他的AI,有没有什么好的底层的项目,然后就给我推荐了xv6,然后我就迈入xv6的天堂了。

不过,事实证明,xv6并不是很适合初学者直接进入这个课程,我就算是之前接触过8086汇编,自认为自己的底子还不错,但是操作系统和计算机组成原理都没有接触过,然后到结束发现xv6是很难的,适合有些基础的人来学习这个项目,这样能更容易的消化,否则,就必须接受长时间的无及时反馈,这个战线真的很长。

Statistics

Coding : 58+h reading : 60+h

toatl: 118+h

Done

xv6的学习,我是看的官方提供的书籍,因为我并不是很喜欢看视频,知识密度太低,当然看书也容易困,容易忘。然后xv6的主要题目都是每次看完一章后的实验也就是lab,

我就是按着官方的实验lab走的

  • Lab util: Unix Utilities
  • Lab syscall: System Calls
  • Lab pgtable: Page Tables
  • Lab trap: Traps
  • Lab cow: Copy-On-Write
  • Lab thread: Multithreading
  • Lab net: Network driver
  • Lab lock: Parallelism/Locking
  • Lab fs: File System
  • Lab mmap: Mmap

就像我上面说,这个战线很长,我每周都会用很长的时间来去看xv6的官方文档,然后再用很长的时间去理解要使用的代码。

这个挑战是很大的,因为对底层的知识几乎为0,我需要看很多的代码,去理解要去干嘛,而且RISCV汇编,我也是第一次接触,也是头一次才知道有CISC和RISC这个两个不同的汇编语言。

Harvest

尽管长时间的无反馈,但是收获也是很多的。

  1. 知道了用户态如何调用系统函数,也就是trap的过程,需要从用户态陷入的内核态,再从trap.c中找到对应的系统调用,然后在内核态中执行对应的函数,然后使用copyout函数将结果返回给用户态。
  2. 知道了内核态如何调用用户态,也就是syscall的过程,需要从内核态陷入的用户态,然后从syscall.c中找到对应的用户态函数,然后调用对应的用户态函数,然后使用copyin函数将结果返回给内核态。
  3. 知道RISCV数据的存放的规则,调用的函数的参数会存放在a0-a7中,返回值会存放在a0中,然后从a0中获取返回值。
  4. 也根据实验的要求看过RISCV的特权手册,专门找过PTE页表的权限位应该放在哪
  5. 知道了虚拟地址和物理地址的寻找,转换,还有页表,以及TLB的工作原理。
  6. 还有关于COW机制的实现,他涉及到fork和trap的联动,要在使用的时候才去分配物理内存,并设置相应的权限位。
  7. 多线程中信号量,唤醒,虚假唤醒,互斥锁,空转,锁的顺序和死锁,还有内存屏障,以及关于减少锁竞争所提出的每个CPU一个锁,并实现的偷页的机制,来提高执行效率。
  8. 还专门看了《英特尔PCI高速以太网控制器系列软件开发者手册》,这个名字比我命都长,我也是第一次看这种手册,里面的东西很多,让我误以为所有的东西都是要记住的,但是这也是不可能的,实际使用的东西并不多,尽管这个实验并不是自己做的,不过倒是知道RX,TX以及他们的从环中获取数据等的过程。
  9. 至于mmap,我现在还没有能力来做这个实验,但是我大概了解了一下他的实现的过程,先在allocprocz中初始化vma数组参数,然后在sysfile中定义mmap和munmap,然后在mmap的时候校验参数,然后寻找vma然后初始化,在page fault的时候,在寻找一个空闲空间然后进行映射,顺便把数据写进去,最后就是释放,然后改一下exit退出时的清理vma和fork时复制vma。

能力方面,现在起码不再是0了,有上面这些基础了,尽管还有很多的东西没有掌握到,但是,我还在学嘛。

TODO

对当前项目来说:剩下的一点算是一点小遗憾吧,Mmap这个实验因为现在没有能力可以支撑我去做,只能暂时搁置了,不过也不是没有收获,我专门看了一下题解,了解了大致的思路,至于具体的是实现,就可以等到学rCore的时候,或者做Toy OS的时候,专门再去实现,那个时候,mmap作为最优雅的实验,一定会把我推过去解决mmap的

对以后来说:我选择了xv6或许是个艰难的底层的开始,也筛选出来,我确实可以走底层,毕竟要是真的学不下去的话,我连mmap我都做不到这,更遑论去了解一下,所以,xv6是我的一个开始,底层的路还很长,现在我还是属于坐井观天的状态,下面的时间,我的打算就是去先做完我的Nand2Tetris,然后去学习rCore顺便做自己的ToyOS,有时间去看linux内核源码,我还是想从User-->Developer,哈哈

当然,我倒是还想专门补一下,makefile的使用,CMake,以及一些linux上的性能分析工具,慢慢来吧,时间还很长。

Summary

这算是我的第一个底层的项目的完结吧,暑假实现的那个redis只能算是检验一下自己是否有耐心学习底层的东西,我嘛,就是想看看底层的样子,想把黑盒变成白盒,在xv6之后,再去看linux,视线开始变得清楚,我知道这个东西是怎么从用户态到内核态,然后从内核态转到用户态,我知道参数是怎么传递的,我知道.......

嗯,这个项目带给我都东西很多,我也不再是嘴上说着要学底层的人,而是进入底层的人了,感觉自己有点自大,哈哈,反正也没啥

反正kernel,os很精美,漂亮,天才,很多东西都值得我去看一看。

[  OK  ] fs: syncing xv6 file system
[  OK  ] fs: unmounting root (/) and flushing log
[  OK  ] net: e1000 driver stopped (tx idle, rx ring flushed)
[  OK  ] mm: COW pages freed: 42, TLB shootdowns: 7
[  OK  ] mm: page tables reclaimed, kalloc slabs released
[  OK  ] trap/syscall: pending signals cleared, ticks: 12345
[ WARN ] mmap: feature disabled in this build; skipping VMA teardown
[  OK  ] arch/riscv: SBI shutdown requested (hartid=0)
[  OK  ] power: system is powering down
reboot: Power down