2024春夏季开源操作系统训练营Blog-第二阶段-罗健峰
开头
对于操作系统这门课上,我是比较薄弱的,就目前在写此总结之余,想起来我还是感觉有些吃力,主要的困点和难点在于我在训练营开始学习之前,学习过操作系统但没有这么深入,仅仅停留在简单的进程、线程和一些简单的调度算法,再一个就是我本身的学习和工作都在应用层,CPU指令集、硬件这一块的理解还是不太深入。但总体来讲我还是比较高兴自己能够坚持下来,回首一看,真是不容易,要补的,要学习的还是非常多。我接下来的打算就是反复细致的再回首,好好吃透rcore,在rcore的基础上想实现一些其他的功能,同时迎接第三阶段的学习。
好了,回归正题,我将以各章所遇到的情况分别总结。
第一章
第一章的代码树比较简单,主要的内容还是让同学们对操作系统有个大致的启动流程。
- 用
qemu
来模拟基于risc-v
指令集的裸机环境。 - 将
qemu
的启动地址设置为rustsbi的地址来引导操作系统的入口函数。同时接触到第一次risc-v汇编语言(entry.asm)。 - 剥离rust基于特定操作系统的用户标准库。
- 一些OS的基础库(日志、标准输出、sbi、异常处理、内存布局等等)
最后运行裸机环境下的os,输出hello world!,此时的os其实不叫os,可能更像是一个库函数。整个计算机的资源都为它一个程序服务。
第一章还是比较简单,没有遇到太大的问题。
第二章 批处理系统
第二章的主要内容是risc-v指令集的特权级机制。
由于第一章是运行单个程序、更多的是一个函数库的使用。
第二章在基于特权级机制下,我们将多个程序一起打包在一起,在第一个程序执行完后,就会自动的执行下一个程序,但要注意的是目前执行的程序都不是全部加载到内存里面的,而是在我们约定好的一个具体的物理地址上,同时特权级机制保障了程序在运行过程中发生错误时,能够触发异常陷入trap进而从用户态转入到内核态去执行和处理异常,进而保证程序错误不会影响接下来的程序运行。
第二章也比较好理解和简单。
第三章 多道程序与分时任务
第三章在第二章的基础上,从一个一个加载到固定内存地址去执行,到一次性全部加载到内存里执行,减少任务切换的开销,同时可以并发的执行多个用户程序。
最重要的是实现了yield系统调用来主动放弃处理器的执行权,
进而可以让OS来调度一个任务的执行还是强制打断,其中打断需要保存上下文,在下一个时间片时恢复原先程序的上下文状态,采用时间片轮转算法调度用户程序。
同时引申出了其他的调度算法,也是一个比较值得研究的地方。后面有时间了还是想看看windows和linux内核的调度算法,学习学习。
第四章 地址空间
由于前面的OS,应用程序都是运行在真实的物理内存上的,任务多了,给应用程序员带来了很大的麻烦,他们在写程序的时候得仔细考虑一下应用该在哪个内存区间内执行,不会影响其他程序和自身程序的运行,再一个就是操作系统有义务来管理程序的运行,和减少上层应用程序员的心智负担,让他们不需要考虑程序的具体运行和内存的分布。
所以说我们引入了一个新的抽象层,地址空间。
实现地址空间不单单是os来做的,在risc-v指令集的硬件设计上也有实现,主要的参与者是MMU,其中stap
寄存器是来开启risc-v指令集的分页机制的
通过设置stap
寄存器来开启,目前OS实现的是SV39分页机制。
基于SV39的分页机制,就可以通过 va -> vpn -> ppn -> pa的关系,从虚拟地址转换到物理地址。
其中os维护了这一映射关系,在代码中的体现是PageTable
和相关的工具函数。
注:
运行时,内核要运行在内核的自己的地址空间中,同时它还得需要知道具体的物理内存地址,能读取到应用中的数据。我们引入了跳板机制。
在每一个程序的最高位地址空间中都注入了跳板,以达到操作系统能读取到应用程序的方便,同时补上risc-v寄存器不够存储上下文的情况。
第五章 进程及进程管理
在第四章地址空间的基础上,我们把前面所谓的任务,升级为进程,其实本质上来讲就是进程。
我们对任务建立新的抽象:进程
引入进程相关的状态。
我们引入了进程相关的内容,整个项目的进程管理是一颗树,同时实现了一些进程相关的系统调用,fork
、exec
、waitpid
等。
这颗进程管理树,是通过用户初始化进程展开的,这个进程是被内置在我们操作系统中的,其他的进程皆可以通过fork + exec
创建和执行。
同时实现了新的stride调度算法,同时设置相关的进程优先级。
这一章的内容是比较多的,当时我在学习的时候还是废了老大劲了,目前准备在写完总结之后再仔细研究研究,准备换个新的进程调度算法。
第六章 文件系统与I/O重定向
这一章,我还没太细致的研究,但总体来讲主要是要明白文件系统的管理方式,其中目录和文件的区分。
easy-fs的磁盘布局
sb | bitmap | diskInode | 数据块位图 | 数据块区域 DataBlock
第七章 进程间通讯
- 主要是进程与管道。
- 一些进程之间的通讯方式,通过管道
后面的想法是通过消息队列来实现进程之间的通讯,目前有一些语言的同步方式就是使用的消息队列。
第八章 并发
没有和前面的系统前向兼容,主要是为os实现锁机制和检测死锁,以及如何恢复,解开锁。
一些死锁算法。
总结
还是非常感谢开源操作系统社区这个平台,文档V3和2024s写的非常好和细致,在整个阅读下来非常舒服,同时也学到了很多的新东西。RAII的设计模式有了更加深刻的体会,也学会了qemu、gdb、make等工具的使用,加深了对rust语言的学习。
最后,非常感谢!