virtual addr (KERNBASE~KERNBASE+KMEMSIZE) = physical_addr
    (0~KMEMSIZE)

    这样只要给出一个虚地址和一个物理地址,就可以设置相应PDE和PTE,就可完成正确的映射关系。

    如果我们这时需要按虚拟地址的地址顺序显示整个页目录表和页表的内容,则要查找页目录表的页目录表项内容,根据页目录表项内容找到页表的物理地址,再转换成对应的虚地址,然后访问页表的虚地址,搜索整个页表的每个页目录项。这样过程比较繁琐。

    我们需要有一个简洁的方法来实现这个查找。ucore做了一个很巧妙的地址自映射设计,把页目录表和页表放在一个连续的4MB虚拟地址空间中,并设置页目录表自身的虚地址<—>物理地址映射关系。这样在已知页目录表起始虚地址的情况下,通过连续扫描这特定的4MB虚拟地址空间,就很容易访问每个页目录表项和页表项内容。

    具体而言,ucore是这样设计的,首先设置了一个常量(memlayout.h):

    VPT=0xFAC00000, 这个地址的二进制表示为:

    1111 1010 1100 0000 0000 0000 0000 0000

    高10位为1111 1010
    11,即10进制的1003,中间10位为0,低12位也为0。在pmm.c中有两个全局初始化变量

    pde_t * const vpd = (pde_t *)PGADDR(PDX(VPT), PDX(VPT), 0);

    并在pmm_init函数执行了如下语句:

    boot_pgdir[PDX(VPT)] = PADDR(boot_pgdir) | PTE_P | PTE_W;

    这些变量和语句有何特殊含义呢?其实vpd变量的值就是页目录表的起始虚地址0xFAFEB000,且它的高10位和中10位是相等的,都是10进制的1003。当执行了上述语句,就确保了vpd变量的值就是页目录表的起始虚地址,且vpt是页目录表中第一个目录表项指向的页表的起始虚地址。此时描述内核虚拟空间的页目录表的虚地址为0xFAFEB000,大小为4KB。页表的理论连续虚拟地址空间0xFAC00000~0xFB000000,大小为4MB。因为这个连续地址空间的大小为4MB,可有1M个PTE,即可映射4GB的地址空间。

    但ucore实际上不会用完这么多项,在memlayout.h中定义了常量

    表示ucore只支持896MB的物理内存空间,这个896MB只是一个设定,可以根据情况改变。则最大的内核虚地址为常量

    所以最大内核虚地址KERNTOP的页目录项虚地址为

    最大内核虚地址KERNTOP的页表项虚地址为:

      在pmm.c中的函数print_pgdir就是基于ucore的页表自映射方式完成了对整个页目录表和页表的内容扫描和打印。注意,这里不会出现某个页表的虚地址与页目录表虚地址相同的情况。

      print_pgdir函数使得 ucore 具备和 qemu 的info pg相同的功能,即print pgdir能
      够从内存中,将当前页表内有效数据(PTE_P)印出来。拷贝出的格式如下所示:

      上面中的数字包括括号里的,都是十六进制。

      主要的功能是从页表中将具备相同权限的 PDE 和 PTE
      项目组织起来。比如上表中:

      • PDE(0e0):0e0表示 PDE 表中相邻的 224 项具有相同的权限;
      • c0000000-f8000000:表示 PDE 表中,这相邻的两项所映射的线性地址的范围;
      • 38000000:同样表示范围,即f8000000减去c0000000的结果;
      • urw:PDE 表中所给出的权限位,u表示用户可读,即PTE_U,r表示PTE_P,w表示用
      户可写,即PTE_W。

      表示仅 1 条连续的 PDE 表项具备相同的属性。相应的,在这条表项中遍历找到 2
      组 PTE 表项,输出如下:

      注意:

      自映射机制还可方便用户态程序访问页表。因为页表是内核维护的,用户程序很难知道自己页表的映射结构。VPT
      实际上在内核地址空间的,我们可以用同样的方式实现一个用户地址空间的映射(比如
      pgdir[UVPT] = PADDR(pgdir) | PTE_P | PTE_U,注意,这里不能给写权限,并且
      pgdir 是每个进程的 page table,不是
      boot_pgdir),这样,用户程序就可以用和内核一样的 print_pgdir
      函数遍历自己的页表结构了。