操作系统 Lab 2


Lab 2

功能实现

sys_get_time & sys_task_info

  1. 传入的 ts: *mut TimeValti: *mut TaskInfo 是虚拟地址, 只需通过 PageTable::from_token(current_user_token()) 手动查询页表, 将其转换为对应的物理地址, 其他实现与 ch3 完全相同.

sys_mmap & sys_munmap

  1. TASK_MANAGER 实现 set_task_mapping(&self, start: usize, len: usize, port: usize)set_task_unmapping(&self, start: usize, len: usize) 方法分别用于虚存的映射与回收.
  2. set_task_mappingset_task_unmapping 都从需要映射的 vpn 通过 memory_set.translate(vpn) 得到对应页表项 entry, 并分别保证其 V 位为 0/1.
  3. set_task_mapping 根据参数 port 设置相应的 MapPermission 位 (包括 U 位), 调用 memory_set.insert_framed_area(...).
  4. set_task_unmapping 根据参数 start 找到区域在 memory_set 中对应的 map_area, 调用 map_area.unmap(&mut memory_set.page_table).

问答题

  1. 请列举 SV39 页表页表项的组成, 描述其中的标志位有何作用?

    答: 页表项 [53:10] 位是物理页号, [7:0] 位是标志位, 其他为保留位, 由低到高为:

    • V: 页表项是否合法;
    • R: 页表项对应的页面是否可读;
    • W: 页表项对应的页面是否可读写;
    • X: 页表项对应的页面是否可执行;
    • U: 页表项对应的页面是否在 U 态下可访问;
    • G: 页表项对应的页面是否为全局页面;
    • A: 页表项对应的页面是否被访问过;
    • D: 页表项对应的页面是否被修改过.
  1. 缺页指的是进程访问页面时页面不在页表中或在页表中无效的现象, 此时 MMU 将会返回一个中断, 告知 os 进程内存访问出了问题. os 选择填补页表并重新执行异常指令或者杀死进程.

    1. 请问哪些异常可能是缺页导致的?

      答: Instruction page fault, Load/AMO page fault, Store/AMO page fault 都是缺页导致的异常.

    2. 发生缺页时, 描述相关重要寄存器的值.

      答: 相关重要寄存器如下:

      • scause: 缺页异常发生时, 该寄存器的 Interrupt 位记 0, 表示异常发生; Exception Code 记录响应的缺页异常种类.
    • stval: 记录导致缺页异常的虚拟地址.

      • stvec: 记录异常处理程序的入口地址.
      • sstatus, sepc, sscratch 在 ch3 报告中已描述过.

      缺页有两个常见的原因, 其一是 Lazy 策略, 也就是直到内存页面被访问才实际进行页表操作. 比如, 一个程序被执行时, 进程的代码段理论上需要从磁盘加载到内存. 但是 os 并不会马上这样做, 而是会保存 .text 段在磁盘的位置信息, 在这些代码第一次被执行时才完成从磁盘的加载操作.

    1. 这样做有哪些好处?

      答: Lazy 策略避免了页面被加载到内存中但未被访问就被淘汰, 减少了不必要的 I/O 操作.

      其实, 我们的 mmap 也可以采取 Lazy 策略, 比如: 一个用户进程先后申请了 10G 的内存空间, 然后用了其中 1M 就直接退出了. 按照现在的做法, 我们进行了很多没有意义的页表操作.

    2. 处理 10G 连续的内存页面, 对应的 SV39 页表大致占用多少内存 (估算数量级即可)?

      答: SV39 分页模式的页面大小为 4KB, 单个页表项大小为 8B, 因此页表占用内存至少为

  2. 请简单思考如何才能实现 Lazy 策略, 缺页时又如何处理?

    答: 进程开始时仅分配页表结构, 不分配实际的物理页面; 触发缺页异常时, 由中断处理函数查找磁盘, 分配物理页面, 并更新页表.

缺页的另一个常见原因是 swap 策略, 也就是内存页面可能被换到磁盘上了, 导致对应页面失效.

  1. 此时页面失效如何表现在页表项 (PTE) 上?

    答: 页面失效时, 会将相应页表项的标志位 V0.

  1. 为了防范侧信道攻击, 我们的 os 使用了双页表. 但是传统的设计一直是单页表的, 也就是说, 用户线程和对应的内核线程共用同一张页表, 只不过内核对应的地址只允许在内核态访问.

    1. 在单页表情况下, 如何更换页表?

      答: 单页表实现在用户进程切换时, 需要更换页表, 加载新地址空间.

    2. 单页表情况下, 如何控制用户态无法访问内核页面?

      答: 将内核页表中页表项的 U0.

    3. 单页表有何优势?

      答: 在内核态和用户态转换时不需要软件更换页表, 效率更高.

    4. 双页表实现下, 何时需要更换页表? 假设你写一个单页表操作系统, 你会选择何时更换页表?

      答: 双页表实现在用户进程切换、自陷时需要切换页表; 我会选择在切换用户进程时更换页表.


文章作者: Chengsx
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Chengsx !
  目录