第一阶段总结报告
其实大多写在日记或者博客里了,这个总结文档可能很多是从日志里摘抄的,选择我一个月学习后觉得最精华的部分
日记
博客
rust 学习
- match 模式匹配是一个非常有魅力的设定,能像switch一样区分出各种各样可预见的值,还能进行匹配的赋值,在语义上有极其强大的表达能力;此外,rust中区分表达式和语句使得match这个行为本身也能有一个值,像是三目运算符的加强版
- 实际上模式匹配无处不在,解构也是一种匹配,在js里非常常见而且优雅,@绑定给match的项增加了表达能力(可以用于进一步约束) 写在日记里了,
- 生命周期
- 生命周期标注并不会改变任何引用的实际作用域,帮助推导(隐形=>显性
- 生命周期消除三原则
- 每一个引用参数都会获得独自的生命周期
- 若只有一个输入生命周期(函数参数中只有一个引用类型),那么该生命周期会被赋给所有的输出生命周期,也就是所有返回值的生命周期都等于该输入生命周期
- 若存在多个输入生命周期,且其中一个是 &self 或 &mut self,则 &self 的生命周期被赋给所有的输出生命周期
- 不符合三原则就得手标,其实本质上都有标,只是编译器进行消除来减少手写
RV 学习
- 看了《计算机组成与设计:软硬件接口RV》的第一章,感觉没太多新接收的概念,大多以前有了解,讲了计算机硬件发展的历程,然后和评判计算机性能的指标。有意思的是八个伟大的思想:
- 面向摩尔定律的设计 设计芯片的时候要考虑未来工艺,需要超前点
- 使用抽象简化设计
- 加速经常性事件
- 通过并行提高性能
- 通过流水线提高性能
- 通过预测提高性能
- 存储层次 Memory Hierarchy
- 通过冗余提高可靠性
- RV 的指令是定长的
- R型(用于寄存器)
- I型(用于带常数的算数指令和加载指令)
- S型(用于Store)
- RV 的同步机制
- atomic exchange原语
- 指令对
- 用户模式、机器模式、监管者模式三种状态
- 切换模式过程中对控制状态寄存器(CSR,八个)的使用
lab1
- rust实现特权级的切换
- 跟RV手册第十章里一样,主要就是几个CSR的保存和切换
- 保存CSR,陷入trap,调用trap_handler,之后再通过CSR返回用户态的状态
- 多道程序的加载:把应用程序载入不同的base_addr
- 任务切换:主动的yield,类似以前写过的jyyOS课的协程,只是这个在操作系统实现
- 分时多任务(抢占式调度),利用SBI的SBI_SET_TIMER能力,做到在一定时间后触发中断,然后在trap_handler的match中增加一个时间片中断处理,跟上面的任务切换一样
- 该指令之后 sp 和 sscratch 中的值分别有什么意义?
- csrrw sp, sscratch, sp
- csrrw r1, r2, r3的意思是把 r2 写进 r1 ,把 r3 写进 r2 ,在上面就是交换 sp 和 sscratch 的意思。
- sp 原来是用户栈,sscratch 原来是内核栈,交换后 sp 指向 kernel stack, sscratch 指向 user stack
lab2
- 学到了引入虚存后的 OS 是如何处理用户态传入的地址的
- 转换后再对物理地址动手
- 完成了 sys_get_time 和 sys_get_info 的重写
- 核心其实就是把 virt_addr 转换成 phys_addr ,然后再将数据类型强转写入 *phys_addr
- 实现了一个 virt2phys_addr() 函数,通过查页表得到物理地址
- mmap 和 munmap 是如何工作的
- 找到物理页帧并映射上去
- 三级页表的结构,页表项的组成
- 在写 mmap 时踩坑了
- 排查良久没看出问题,去偷瞄了两眼仓库里其他人的代码,发现我的设计就有问题
- 没有用到 MemorySet 的抽象,而是直接去操作物理帧,所以分配后的物理帧没有被管理到,因此 frame_allocate() 后那个物理帧会自动 drop 掉,而资源又是RAII式的管理方式,自定义的 drop 函数里dealloc了这个帧,因此第二次 mmap 的时候又用上了原来的那一帧
lab3
- 进程管理的基础是 fork 和 exec (按伟大导师 jyy 说的,前者是状态机的复制,后者是状态机的重置)
- rCore 里进程管理机制由一个 Processor 任务管理器负责,这个 Processor 里还有一个 idle_task_cx ,表示一个空闲的任务,实际上就是两个不同任务切换中间的一个状态,一个任务让出后会来到这个 idle_task_cx,再分配给下一个任务,这样在只有一个任务的时候也能调度给同一个任务
- 感觉调度跟自己以前写的南大OS的协程差不多,其实都是切换上下文的过程,不过有点好奇什么说切换线程时发生中断,速度就会比在用户态切换慢?我的理解看来都是切换上下文呀,难道是切换不同类型的上下文效率差很多吗
- 完成了 spawn
- 其实就是从 fork 和 exec 的实现各偷一点,从前者偷新建一个上下文,后者偷修改状态机
lab4
- 磁盘里管理文件位置的组件叫 DiskInode,而Inode是DiskInode 在内存里的体现(载体?)
- 一个磁盘 fs 有五个块
- super block
- inode bitsmap
- data bitsmap
- inodes
- data blocks
- 其中两个 bitsmap 展示了磁盘各块使用情况
- 一个磁盘可以有多个分区,每个分区都是单独的fs(如windows常见的c、d盘)
- 第一次接触link和unlink的实现,以前使用得很少
- 硬链接是把目录表里的 inode 索引修改成某个文件
- 软连接是把目录表里的 inode 索引修改成另一个文件所在目录项(类似重定向到另一个名字)
lab5
WIP