OS Lab2 Report

OS Lab2 实验报告

实现功能

首先重新实现 sys_gettimeofdaysys_task_info,用户传的指针是用户页表中的虚拟地址,内核使用 copyout 接口向用户给定虚拟地址写入数据。

然后在 syscall.c 中增加了 sys_mmapsys_munmap 两个系统调用,sys_mmap 的核心是调用 kalloc 申请匿名物理内存并使用 mappages 映射到由 start 开始的某一段虚存,sys_munmap 中核心则是调用 uvmunmap 取消虚存映射。

问答题

第 1 题:SV39 页表项

SV39 页表项组成如下所示:

1
2
3
4
5
 63      54 53                             10 9   8 7 6 5 4 3 2 1 0
+----------+--------------------------------+-----+-+-+-+-+-+-+-+-+
| reserved | PPN | RSW |D|A|G|U|X|W|R|V|
+----------+--------------------------------+-----+-+-+-+-+-+-+-+-+
10 44 2 1 1 1 1 1 1 1 1

最高 10 位为保留位,中间 44 位为物理页号 PPN(非叶子节点即指向下一级页表起始位置的物理页号),最低 10 位为标志位。标志位有以下作用:

  • V:有效位,表示页表项是否有效。
  • R, W, X:对叶节点页表项,这些位分别表示页面是否可读、可写和可执行;对非叶节点页表项,三个位均为 0(且 V 位为 1)表示是合法页目录表项,指向页面表的下一级。
  • U:用户位,表示对应虚拟页面是否可在用户态下访问。
  • G:全局位,表示对应的页面是否是全局的,若是全局的在进程切换时不必刷新该页的 TLB 缓存。对于非叶结点页表项,全局设置意味着页表后续级别中的所有映射都是全局的。
  • A:访问位,表示对应的页面是否被访问过,为页面置换算法提供信息。
  • D:脏位,表示对应的页面是否被修改过,若修改过换出内存页时需要写回磁盘。
  • RSW:为内核程序预留,硬件不会对此做任何其他操作。

第 2 题:缺页

  1. 请问哪些异常可能是缺页导致的?
    常见因缺页引起异常的场景包括:
    • 地址空间映射关系未建立:用户进程访问未经物理内存映射(未向操作系统申请)的虚拟地址;或申请的虚拟地址尚未分配实际的物理页面(lazy策略),在首次访问时会触发缺页异常;
    • 地址空间映射关系已建立,但访问的页面被交换(swap)到磁盘,不在内存中;
    • 访问的地址空间不合法(如用户态访问内核地址空间),或访问页面的执行权限不够(如修改只读页面)。
  2. 发生缺页时,描述相关的重要寄存器的值。
    sscratch 中是发生缺页进程的 trapframe 地址,satp 中是发生缺页进程的页表根地址,sepc 中是发生缺页异常的指令地址,mcause 中 Interrupt 位是 0(表示异常),Exception Code 是 12、13 或 15。
  3. Lazy 策略有哪些好处?
    有助于节省物理空间,减少不必要的页表操作。
  4. 请问处理 10G 连续的内存页面,需要操作的页表实际大致占用多少内存(给出数量级即可)?
    一个叶子节点页表项可映射 4KB 物理内存,一个物理页面包含 512 个页表项,可映射 2MB 内存,则处理 10G 连续页面需要三级页表 10G / 2M = 5K 个;这 5K 个连续三级页表对应二级页表个数大约为 5K / 512 = 10 << 5K,故在数量级上可忽略一级二级页表占用的内存。由此估计,所需的页表大致内存为 5K * 4KB = 20MB。
  5. 请简单思考如何才能在现有框架基础上实现 Lazy 策略,缺页时又如何处理?描述合理即可,不需要考虑实现。
    为每个用户进程分配一张表,记录其申请的虚拟内存地址,在申请时仅在表上记录,暂时不映射到真实物理内存;当发生缺页时,首先查找该表判断是否访问的地址是否已经申请过,若已经申请过则将该地址从表上移出,并分配一段与访问空间大小相应的物理内存,修改页表建立映射,然后返回缺页异常的指令继续执行。
  6. 内存页面可能被换到磁盘上了,导致对应页面失效。此时页面失效如何表现在页表项(PTE)上?
    对应叶子节点 PTE 的 V 位(有效位)为 0,但 R/W/X 位不全为 0。

第 3 题:单页表和双页表

  1. 单页表情况下,如何更换页表?
    同样通过 csrw 修改 satp 寄存器,并使用 sfence.vma zero, zero 刷新 TLB 实现更换。
  2. 单页表情况下,如何控制用户态无法访问内核页面?
    将内核页面对应的页表项 U 位置 0。
  3. 单页表有何优势?
    只需在进程切换时更换页表、刷新 TLB,在同一进程的用户态和内核态之间切换时(如异常处理、系统调用)不用更换页表和刷新 TLB,减少时间开销,提升程序效率。
  4. 双页表实现下,何时需要更换页表?假设你写一个单页表操作系统,你会选择何时更换页表?
    进程切换和用户态、内核态之间的切换都要更换页表。可以选择在进程调度时更换页表。