0%

rCoreCamp2022第一阶段报告-werifu

第一阶段总结报告

其实大多写在日记或者博客里了,这个总结文档可能很多是从日志里摘抄的,选择我一个月学习后觉得最精华的部分

日记
博客

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