feat(pgtbl): 实现统计最近访问页表、独立内核页表
Print a page table:遍历当前进程页表,如果状态是可用,则递归打印
- 遍历顶级页表,如果可用,则进入其所指的中级页表,直到最终页表,然后打印pa数据
- 需要用到位移(内置宏定义),因为页表中所指的地址是下一级页表的地址,所以需要转换成pagetable_t类型才能正确访问,通过对内核内存地址进行位移操作,获取对应的下标来获取下级页表地址。
Detecting which pages have been accessed:给定地址,统计该地址之后指定范围内已被访问过的页表
- 新增页表标记位,用来标记当前页表是否被访问过
- 在统计页表是否被访问之后,需要将访问标记位置为0
- 需要将内核数据写到用户态的数据之中
- 访问,即在walk中将获取到的页表进行标记、分配页表的时候也标记
用户进程独立内核
- 用户进程独立内核页表
- 因为所有进程共享一个全局内核页表,同时这个页表中的内核栈各自独属于某个用户进程。
- 所以当用户进程陷入内核的时候,有一定风险导致访问到非当前用户的内核栈
- 实现思路
- proc结构体新增一个内核页表结构
- 将必要的信息映射到用户内核页表中,如代码段之类,可参考全局页表初始化时所做的操作
- 在copyin和copyout的时候,使用用户进程的内核页表
- 调度的时候,也需要使用用户当前的内核页表,结束的时候,需要切回全局页表
- 进程结束的时候,需要释放页表,但不能释放叶子节点的内存,因为它可能被其他进程或者内核所使用。
- 用户进程独立内核页表映射用户数据
- 在独立内核页表的基础上,将用户数据也映射在低地址区域
- 在原本的映射区间中,0x80000000L之下是设备之类的映射。
- 而用户地址是从0开始增长,刚好可以将其映射到独立内核页表中的0-plic的区域之间。
- 实现之后的效果,即在内核态读写用户进程数据的时候,不需要借助其页表也能进行读写(使用进程独用的内核页表),此时内核页表已经映射过了,不用遍历用户页表。
- 实现思路
- 映射用户地址到独立内核页表低地址地方,同时需要给予内核权限。
- fork、exec、sbrk等需要操作用户数据的地方,需要更改
- 访问操作是可以直接访问用户虚拟地址