xv6(RISC-V/C)能否手动修改页表PTE?页表打印PTE值不一致求解
xv6三级页表PTE值疑问
我在给xv6实现三级页表时,遇到了PTE值的困惑:打印页表时,开头输出的page table address(比如...87f49000)和第二行的PTE值(比如...21fd1401)始终不一致。我原本以为这两个值应该相同,有人说这是操作系统调度随时间变化导致的正常情况。
我是不是漏了什么,才让页表输出不符合预期?我只想让前两个页表的PTE值看起来和预期一致!
预期输出(PTE地址部分与页表地址相同)

实际输出

我的代码(无需关注)
static int level = 0; static int print_end = 0; static uint64 vadd_lv0 = 0; static uint64 vadd_lv1 = 0; static uint64 vadd_lv2 = 0; static pte_t pte = 0; void vmprint(pagetable_t pagetable) { if (level == 0){ printf("page table %p\n", pagetable); print_end = 0; pte = pagetable; } // iterate 512 PTEs for (uint64 i = 0; i < 512; i++) { uint64 va = 0; switch(level){ case 0: vadd_lv0 = i<<30; va = vadd_lv0; break; case 1: vadd_lv1 = i<<21; va = vadd_lv0+vadd_lv1; break; case 2: vadd_lv2 = i<<12; va = vadd_lv0+vadd_lv1+vadd_lv2; break; } pte_t t = pagetable[i]; if (t & PTE_V) { uint64 pa = PTE2PA(t); if (level==0 && i==255) print_end = 1; if (level != 0 && !print_end){ printf("|"); }else if (level!=0){ printf(" "); } for (int j = 0; j < (level-1)*4+3; j++) printf(" "); printf("+-- %d: pte=%p va=%p pa=%p",i, t, va, pa); printf((t&PTE_V)?" V":""); printf((t&PTE_R)?" R":""); printf((t&PTE_W)?" W":""); printf((t&PTE_X)?" X":""); printf((t&PTE_U)?" U":""); printf((t&PTE_D)?" D":""); printf("\n"); // PTE without any WRX bit set points to low-level page table if ((t & (PTE_W|PTE_R|PTE_X)) == 0){ level++; vmprint((pagetable_t)pa); level--; } } } }
问题解析
核心差异:页表地址 vs PTE值
开头打印的page table address是当前页表本身的纯物理地址;而第二行的PTE值是上级页表中指向当前页表的条目,它不仅包含目标页表的物理地址,还附加了PTE_V(有效位)、PTE_U(用户位)等权限标志位。你看到的PTE值末尾的01就是PTE_V位被置1的结果(xv6中PTE_V是最低位),所以二者必然不同。预期输出的“相同”是视觉假象
预期输出里只显示了PTE值的高地址部分,末尾的标志位被截断或未展示,才会看起来和页表地址一致。实际完整的PTE值一定包含标志位,和纯物理地址有差异。调度变化的说法不成立
同一个进程的页表结构不会随调度随意变化,你看到的不一致是页表结构的正常特性,和调度无关。实现预期效果的方法
如果你想让输出中PTE的地址部分和页表地址相同,打印时只提取PTE中的物理地址部分即可,修改打印行:// 替换原printf行,单独展示PTE的物理地址部分 printf("+-- %d: pte=%p (pa=%p) va=%p pa=%p",i, t, PTE2PA(t), va, pa);或者直接把打印PTE的部分换成
PTE2PA(t),就能看到和页表地址一致的数值。
内容的提问来源于stack exchange,提问作者Chunhao
相关产品推荐
相关产品推荐

