第1~2章
总的来说这两张花的时间是比较久的,因为完全没有学过操作系统,对概念上的理解用了一些时间,真的跟着代码学习的时候,不知道这些代码之间的联系,不知道用户程序和操作系统是怎么联系起来的。
因此总结了一个大概流程:
build.py编译user里面的用户应用程序:
启动qemu和rustsbi,编译os
执行build.rs,将bin文件插入到link_app.S,生成link_app.S
链接
main.rs运行batch.rs,开始批处理
batch.rs首先初始化一个实例:APP_MANAGER: UPSafeCell
从link_app.S里面找到_num_app符号,找到每个app的地址存进app_start数组,然后将其打印出来
然后依次执行应用程序,其中应用程序出现错误或者开始下一个应用程序时,需要有用户态到内核态的切换。需要用到Trap.S
开始批处理
保存Trap上下文,之后进入trap_handler,正常情况下会返回并继续执行下一个应用程序
这个函数不会返回,会一直将加载应用程序并把当前的应用程序的上下文压入内核栈,sret后就会自动执行下一个应用程序,直到完成
第3章
主要是学习分时操作系统,概念上还是比较好理解的
第4章
学习了地址空间,一开始对于这几个概念比较混淆:
- 虚拟地址
- 虚拟页号
- 物理地址
- 物理页号
- 地址空间
后来根据这个图搞懂了
虚拟地址指的是在地址空间里面,数据的地址
虚拟页号指的是虚拟地址字段里面的一个字段,这个字段可以在物理页表上查到一个物理页号,最终通过多级页表,查找到这个虚拟地址对应的物理地址,从而真正在主存读写数据
每个应用的地址空间可以被分成若干个(虚拟) 页面 (Page) ,而可用的物理内存也同样可以被分成若干个(物理) 页帧 (Frame) ,虚拟页面和物理页帧的大小相同
地址空间:一系列有关联的逻辑段:
地址空间是一系列有关联的逻辑段,这种关联一般是指这些逻辑段属于一个运行的程序(目前把一个运行的程序称为任务,后续会称为进程)。 用来表明正在运行的应用所在执行环境中的可访问内存空间,在这个内存空间中,包含了一系列的不一定连续的逻辑段。 这样我们就有任务的地址空间、内核的地址空间等说法了
也就是说,地址空间的逻辑段不一定连续,这就对应了编程题,如果要写的内容太大导致分页,应该直接将内容也分页塞入到其物理地址里面去
第5章
需要记的就是进程是怎么调度的,switch函数的作用
就是最初,先创建一个idle进程,然后将switch的参数设置为idle进程和第一个程序,使得第一个程序可以执行
然后就调用 task 子模块提供的 suspend_current_and_run_next 函数可以暂停当前任务,并切换到下一个任务
这一章完成后,一个应用程序可以主动交出CPU的使用权,这样一来,它需要等待某个资源的时候,CPU就可以去执行其他程序了
第6章
这一章的概念也看得我很晕
主要是:
- 索引节点和文件有什么关系?
- 目录和索引节点又有什么关系?
- 一级索引存在哪里?二级索引指向哪里?
- inode和DiskInode是如何映射起来的?
因此画了这个示意图:
对于lab,感觉比较难的是理解几个inode之间的关系,比如通过文件名如何查找其对应的inode_id?
第7~8章
终于要结束了
第8章的概念比较好理解,对我来说比较难的是理解lab里面死锁检测算法的含义
一开始写的时候只考虑了能否解开一个锁,总感觉哪里不对。后来发现,其实要考虑能否解开所有的锁,因为解锁的顺序是要考虑的,如果只考虑能否解开一个锁,那么这个解锁顺序可能无法实现。