OceanPresent

rCore Lab2笔记


编程题

重写 sys_get_time 和 sys_task_info

由于内核和应用地址空间的隔离, 系统调用 不再能够直接访问位于应用空间中的数据,而需要手动查页表才能知道那些 数据被放置在哪些物理页帧上并进行访问。

可以参考文档中sys_write的重新实现。基本原理就是使用函数translated_byte_buffer可以将应用地址空间中一个缓冲区转化为在内核空间中能够直接访问的形式,然后再进行操作即可。

指针的copy操作可以使用core::ptr::copy_nonoverlapping

在taskinfo踩了坑,同样的代码可以过ch3的测试却没法过ch4的测试,因为使用了get_time_ms函数,有一些精度问题,后来改成get_time_us() / 1000 即可

mmap 和 munmap 匿名映射

mmap函数的作用和签名可参考参考一参考二

比较麻烦的是要弄清申请页和释放页边界,统一使用左闭右开的范围。检查范围和权限是否合法 使用 基本的数值运算或位运算即可;申请空间和释放空间要求 理解memset和pagetable的api作用,合理地使用即可

在样例ch4_umap卡了很久,因为当时mmap和munmap申请内存的范围边界没有理清,注意测试样例有一个地方申请了 PAGE_SIZE + 1的空间,这个申请应该向上取整,申请2页内存

问答题

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

其中 [53 ~ 10] 这 44 位是物理页号,最低的 8 位 [7 ~ 0] 则是标志位。 标志位中:

  • V(Valid):仅当位 V 为 1 时,页表项才是合法的;
  • R(Read)/W(Write)/X(eXecute):分别控制索引到这个页表项的对应虚拟页面是否允许读/写/执行;
  • U(User):控制索引到这个页表项的对应虚拟页面是否在 CPU 处于 U 特权级的情况下是否被允许访问;
  • A(Accessed):处理器记录自从页表项上的这一位被清零之后,页表项的对应虚拟页面是否被访问过;
  • D(Dirty):处理器记录自从页表项上的这一位被清零之后,页表项的对应虚拟页面是否被修改过。

缺页

缺页指的是进程访问页面时页面不在页表中或在页表中无效的现象,此时 MMU 将会返回一个中断, 告知 os 进程内存访问出了问题。os 选择填补页表并重新执行异常指令或者杀死进程。

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

发生缺页时,描述相关重要寄存器的值,上次实验描述过的可以简略。

缺页时操作系统会发生Trap,因此会涉及到Trap处理相关的寄存器,例如通用寄存器、sp、sscratch、sstatus、sepc

从用户态进入内核态页表也需要切换,涉及到satp

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

这样做有哪些好处?

按需获取,节省内存,加快系统速度

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

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

SV39 页表中的每一项都代表一个页面(通常为 4KB)。因此若为所有页面都建立页表项,页表总共需要 10G / 4KB = 2.5亿项。每个页表项占64bit也就是16字节,总内存占用为2.5亿 x 16字节。根据局部性原理,真正频繁用到的页表项只有20%,因此我们可以估计只需要将0.2 x 2.5亿 x 16字节 的页表项放入内存

请简单思考如何才能实现 Lazy 策略,缺页时又如何处理?描述合理即可,不需要考虑实现。

缺页时触发一种特定的Trap,在TrapHandler函数对该类型的trap进行特殊处理,此时根据之前保存 .text 段在磁盘的位置信息来加载应用到内存中

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

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

我们可以在页表项上添加一个特殊的标志,表示该页面是否在内存中。当操作系统尝试访问一个被换出的页面时,硬件会检测到这个标志,并产生一个页面失效(Page Fault)异常。

双页表与单页表

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

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

使用satp寄存器保存页表的初始地址,当用户态或内核态切换时,修改satp的值使其指向对应页表的初始地址(因为是单页表所以本质上指向的是单页表的不同偏移)

单页表情况下,如何控制用户态无法访问内核页面?(tips:看看上一题最后一问)

我们可以在页表项上添加一个特殊的标志,表示该页表项是否属于内核页表。当在用户态访问该页表项,则抛出异常

单页表有何优势?(回答合理即可)

  1. 易于实现。单页表设计在实现上相对简单,用户页表和内核页表采用相同的设计,因此可以更容易地被实现和调试。
  2. 更高效。单页表设计可以减少页表项的查找操作,因为只需要通过简单的映射操作即可找到对应的物理地址。

双页表实现下,何时需要更换页表?假设你写一个单页表操作系统,你会选择何时更换页表(回答合理即可)?

我怎么感觉切换时机一样的=。=??都是:

  1. 用户态和内核态切换时
  2. 不同任务切换时

This website has been running for 3 years 4 months 0 days 16 hours 10 minutes 46 seconds

皖ICP备2021007094号 2021-PRESENT © OceanPresent