本文主要是介绍mit 6.s081 lab3 page tables,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
chapter 3
Print a page table
这个exercise的内容为打印page table,需要实现一个打印函数vmprint,参数为pagetable_t,传入根页表地址,打印对应的pagetable。在这个exercise中只需要打印init进程的pagetable,所以需要在exec函数(exec.c)中添加对进程的pid的判断,如果pid为1,打印该进程的pagetable
打印的例子:
page table 0x0000000087f6e000
..0: pte 0x0000000021fda801 pa 0x0000000087f6a000
.. ..0: pte 0x0000000021fda401 pa 0x0000000087f69000
.. .. ..0: pte 0x0000000021fdac1f pa 0x0000000087f6b000
.. .. ..1: pte 0x0000000021fda00f pa 0x0000000087f68000
.. .. ..2: pte 0x0000000021fd9c1f pa 0x0000000087f67000
..255: pte 0x0000000021fdb401 pa 0x0000000087f6d000
.. ..511: pte 0x0000000021fdb001 pa 0x0000000087f6c000
.. .. ..510: pte 0x0000000021fdd807 pa 0x0000000087f76000
.. .. ..511: pte 0x0000000020001c0b pa 0x0000000080007000
…的数量与页表的level相同,然后是pte在pagetable的index,pte的内容和pa的内容
- 对于pagetable中pte只打印有效的pte(PTE_V位为1),打印三级页表的内容
- pte到pa的转换使用PTE2PA进行转换,pte和pa的差别实际上就是pa中的offset的位数(12 bits)和pte中flag的位数(10 bits)不同,以及每个页表的offset部分都为0
void vmprint_walk(pagetable_t pagetable, int depth) {for (int i = 0; i < 512; i++) {if (((pte_t)pagetable[i] & PTE_V) == 0)continue;for (int j = 0; j < depth; j++) {if (j == depth - 1)printf("..");elseprintf(".. ");}printf("%d: pte %p pa %p\n", i, (pte_t)pagetable[i], PTE2PA((pte_t)pagetable[i]));if (depth < 3)vmprint_walk((pagetable_t)PTE2PA((pte_t)pagetable[i]), depth + 1);}
}void vmprint(pagetable_t pagetable) {printf("page table %p\n", pagetable);vmprint_walk(pagetable, 1);
}
A kernel page table per process
在这个exercise中所需要完成的任务为每个process添加一个独立的kernel page table。
在目前的实现中,在kernel space所使用的pagetable都是在vm.c中声明的kernel_pagetable,在这个exercise中需要为每个process添加一个kernel_pagetable的拷贝,并且在进入到kernel space后使用process中的kernel pagetable。
因此在proc结构体中添加一个变量pagetable_t kpagetable,记录kernel pagetable。每个process的kpageble映射除了kernel stack外与global kernel pagetable一致,具体映射查看kvminit函数。除了kvminit中建立的映射外,还需要在kpagetable需要对对应的process的kernel stack进行映射。在procinit函数中,会为每个process分配一个kernel stack,每个kernel stack的大小为4096 bytes,并且在global kernel pagetable中建立对应的映射。因此在创建process时(allocproc函数),需要为kpagetable分配内存,建立kvminit中的映射关系,并且为kstack增加映射(不需要重新分配kernel stack的内存)。
在进行进程调度时,需要将原来的kvminithart(将satp设为global page table)替换为将satp设置为process中的kpagetable
当process运行结束释放proc时需要删除对应的kpagetable,但不删除kpagetable最终指向的物理内存(叶子节点)
1.在struct proc中添加kpagetable
proc.h
struct proc {
....
pagetable_t kpagetable; // Kernel page table
....
}
2.创建一个kernel pagetable
vm.c
// 创建一个kernel pagetable
pagetable_t kvmcreate() {pagetable_t kpagetable = (pagetable_t) kalloc();
这篇关于mit 6.s081 lab3 page tables的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!