感谢老师和主教们提供的这么一次宝贵的学习操作系统的课程,不管是老师们上课时的专业程度,还是文档的详细度,或是练习的代码,都体现出了老师们对于这门课付出的大量的时间和心血。在第一阶段的学习中,我了解和熟悉了Rust语言的使用方法,并在rustlings中尝试解决各种问题。当然,rust语言也并没有那么容易上手,加上时间有限,在学习第一阶段时候我对rust语言本身还是只有一个概念的雏形,有些rust的语法特性由于缺乏实践没有真正掌握。当然,在第二阶段的学习中,我开始真正尝试使用rust实现系统调用,同时努力学习吸收老师们的代码和思路,不仅能够更加熟练的使用rust语言,还对操作系统有了更清晰的概念。
lab1
lab1的要求为实现sys_task_info
系统调用。其中涉及到两个部分:
- 调用该系统调用时距离第一次调用该task的时间差,可以在
TaskControlBlock
中增加一个字段start_time
以记录对应的task第一次被调用的时间,由于task只可能在run_first_task
和run_next_task
中进行切换,只需要在这里面判断是否是第一次调用并记录时间即可。 - 统计
sys_call
的调用次数,在TaskControlBlock
中通过桶计数即可,所有的syscall都有统一的入口syscall
,它接受参数syscall_id
即桶的序号,只需要通过current_task
方法获取到当前的task,增加相应的值。
lab2
lab2的要求为重写sys_get_time
和sys_task_info
以解决引入虚存带来的错误。
由于引入虚存,内核无法再直接通过*访问用户的地址空间,因此需要根据任务的pagetable手动映射到实际的物理地址,已有代码已经提供了translated_byte_buffer
接口,只需要传入current_user_token和对应的虚拟地址,即可获得实际的物理地址通过*写入。
mm_map
申请内存主要是通过MapArea::new
方法申请一块新的物理内存,并将其存入task所对应的areas,并通过MapArea::map
方法在全局的page_table
中做相对应的映射;mm_umap
则是同过area.unmap
取消映射。
需要注意的点是,MapPermission
中除了port对应的权限外,还要额外增加MapPermission::U
,因为所有操作都是为用户申请的内存,用户一定具有访问权限。
lab3
lab3要求实现sys_spawn
调用,其实spawn和fork非常像,唯一区别在于fork需要继承一些父进程的信息,而spawn不用,因此spawn的实现只需要参考fork即可。
stride调度算法只需要修改run_next_task
中fetch_task
的实现逻辑即可。
另外,通过本章,我还对os中的exclusive_access方法有了更深的理解,之前我一直不是很理解为什么老师们写的代码中存在一些手动drop的元素,本章由于新增了current_process方法,我遇上了两个地方同时申请exclusive_access导致的panic,后来我知道了之前不写drop不出错是因为写的地方的方法都会正常退出,编译器替我自动drop了,但是本章有些地方存在跳转,而跳转是不会自动drop这些申请的,因此需要在跳转前手动drop。
lab4
lab4的要求为实现硬链接,主要是需要熟悉easy-fs的实现逻辑,最主要的结构体就是INode,DiskINode,DirEntry
,DiskINode是easy-fs存在磁盘上用于记录文件位置信息的结构体,INode是DiskINode对用户提供的一个接口结构体,DirEntry表示了文件名和disk_inode_id之间的映射关系,由于本章文件系统较为简单,因此DirEnrty不需要考虑文件路径的问题。
硬链接的思路为,在DiskINode中新增一个记录指向该Node记录的文件被引用的次数的字段,硬链接不需要新建一个一模一样的文件,只需要新建一条DirEnrty指向原文件的DiskINode即可,然后将这个DirEnrty写入ROOT_INODE;删除的逻辑为将对应的DirEnrty覆盖。
lab5
lab5的要求为通过银行家算法检测死锁,实现的算法已经在要求中呈现,通过记录资源对线程的available,allocated,needeed
的值,即可完成相应的检测;其中,available
是记录在线程PCB中,其它两个记录在线程TCB中。由于死锁只可能发生在lock和down资源不够的情况下,因此在这两种条件下判断是否会死锁。
到这一章时我已经对rcore-os的整体框架比较了解了,但是这一章容易导致一些rust语言方面的问题:在unlock和up切换任务时没有及时drop相对应的变量,导致运行时出现了borrow muted的问题,并且因为这个问题报错的行数不是实际产生问题的位置,因此难以排查;外加银行家算法实现如果存在问题比较难排查,因此实现这一章还是耗费了一定的时间的。
另外需要注意的是,这一章需要额外实现sys_get_time
方法,否则测试用例中的sleep
方法是会导致阻塞的。