lab3 难度有点大啊,看完了要求还是不知道需要做啥,挺嘛的。
# Print a page table
第一个 case easymode,没什么注意点的:
static char *t[3] = {".. .. ..", ".. ..",".."}; | |
static void treeprint(pagetable_t pagetable, int level){ | |
for (int i=0; i<512;i++){ | |
pte_t *pte = &pagetable[i]; | |
if(*pte & PTE_V){ | |
pagetable_t pa = (pagetable_t)PTE2PA(*pte); | |
printf("%s%d: pte %p pa %p\n", t[level], i, *pte, pa); | |
if(level!=0){ | |
treeprint(pa, level-1); | |
} | |
} | |
} | |
} | |
void vmprint(pagetable_t pagetable){ | |
printf("page table %p\n", pagetable); | |
treeprint(pagetable, 2); | |
} |
效果图:
这里留下了一个疑问,指针导致是虚地址还是实地址,我觉得应该是虚地址的。
# A kernel page table per process
kernel page 的映射图:
Xv6 has a single kernel page table that's used whenever it executes in the kernel. The kernel page table is a direct mapping to physical addresses, so that kernel virtual address x maps to physical address x.
Xv6 对于所有的进程维护一个相同 kernel page,并且实现虚地址到实地址的直接映射。
过关:
关于 kernel page 和 user page:
即使做了这个 lab case,也对这两个定义模模糊糊的,这个 case 要求给每个进程维护一个单独的 kernel pagetable
,但是这些 kernel pagetable
都是一样的,他们都是完成了上面 kernel pagetable
。
# Simplify
这个 case 要求简化 user 指针的解引用。因为 user 指针是 user mode 下的虚地址,这里有个说明:
If you're writing a application that will run on top of a operating system, that is, in user mode and the operating system uses virtual memory, it will point to a virtual address (or rather, it will point to a physical address but not the same physical address that will in fact be used).
If you're using an operating system without virtual memory or if you're writing (parts) of the kernel code it will point to the physical address.
如果 os 实现了虚拟内存功能,那么这个指针就是一个虚地址,通过这张图可以更好地说明:
这是 user address space 示意图,可以看到但我们从命令行读数据,或者初始化变量时候,我们实际上是放在了 user process 的栈中,每一次调用就压一次栈。所以编译器得到的指针也就是所谓的地址,指向的是这个虚拟的地址空间。通过页表将虚拟的地址转换为实地址:
因为 user 传递给内核的指针其实是 user 的 virtual address,于是当 kernel 想进行 copyin 或者 copyout 的操作就会面临一个尴尬处境,因为 kernel pagetable 和 user pagetable 是两个不一样的表,kernel pagetable 中没有记录 user virtual address 是如何映射的实地址的,因此 kernel 就需要拿着 user pagetable 来先把这个地址解引用来获得实地址。这个 case 需要简化这一步,直接用 kernel pagetable 来映射 user virtual address 也就是用户态指针。