用虚拟地址访问页表

虚拟地址和物理地址是乱序映射的。

一、查看分页的结果

在开启分页后,我们可以使用 info tab 命令看到页表中虚拟地址到物理地址的映射关系。

1
2
3
4
5
6
cr3: 0x000000100000
0x00000000-0x000fffff -> 0x000000000000-0x0000000fffff
0xc0000000-0xc00fffff -> 0x000000000000-0x0000000fffff
0xffc00000-0xffc00fff -> 0x000000101000-0x000000101fff
0xfff00000-0xffffefff -> 0x000000101000-0x0000001fffff
0xfffff000-0xffffffff -> 0x000000100000-0x000000100fff

cr3 寄存器显示的是页目录表的物理地址。左边的虚拟地址,右边的是物理地址。

第一行,虚拟地址是 0x00000000-0x000fffff,这是虚拟空间低端 1M 内存,其对应的物理地址是 0x000000000000-0x0000000fffff。这是第 0 个页表的作用。

第二行,虚拟地址是 0xc0000000-0xc00fffff,这是第 768 个页表的作用。由于第 0 个页目录项和第 768 个页目录项指向的是同一个页表,所以其映射的物理地址依然是 0x000000000000-0x0000000fffff

然后下面的三行,是在创建页表的时候,最后一个页目录表项(第 1023 个目录项)中填入的是页目录表的物理地址。

先来看第三行 0xffc00000-0xffc00fff -> 0x000000101000-0x000000101fff

虚拟地址的高 10 位用来访问页目录表中的目录项,这里高 10 位全是 1,1111_1111b = 0x3f = 1023 ,则访问的是最后一个目录项。该目录项的高 20 位是页目录表本身的物理地址 0x100000。在这里会被认定为是页表地址。线性地址的中间 10 位用来在页表中定位一个页表项,从该页表项中获取物理地址。此时 10 位是 0000_0000b = 0x0,检索到第 0 个页表项,这里存储的是 0x101000,此值被认为是最终的物理页地址。再使用剩余的 12 位,就可以得到最终被映射的物理地址:0x101000+0x000 = 0x101000。因此虚拟地址是 0xffc00000-0xffc00fff,其被映射的物理地址范围是 0x000000101000-0x000000101fff 没有问题。

高 10 位若位 0x3ff,则会访问到页目录表中最后一个页目录项,由于页表中也是 1024 个页表项,故中间 10 位若为 0x3ff,则会访问到页表中最后一个页表项。

来看第四行 0xfff00000-0xffffefff -> 0x000000101000-0x0000001fffff。虚拟地址 0xfff00000 高 10 位是 0x3ff,中间 10 位是 0x300,这是第 768 个页目录项,该页目录项指向的页表与第 0 个页目录项指向的页表相同。所以虚拟地址 0xfff00000 映射为物理地址 0x000000101000 没有问题。

来看第五行 0xfffff000-0xffffffff -> 0x000000100000-0x000000100fff。虚拟地址 0xfffff000 的高 10 位是 0x3ff,中间 10 位是 0x3ff,因此得到的物理页地址是 0x100000。剩余 12 位为 0,所以虚拟地址 0xfffff000 映射为物理地址 0x000000100000

二、总结虚拟地址获取页表中各数据类型的方法

  • 获取页目录表物理地址:让虚拟地址的高 20 位为 0xfffff,低 12 位为 0x000,即 0xfffff000。这也是页目录表中第 0 个页目录项自身的物理地址

  • 访问页目录中的页目录项,即获取页表物理地址:要使虚拟地址为 0xfffffxxx,其中 xxx 是页目录项的索引乘以 4 的积

  • 访问页表中的页表项:要使虚拟地址高 10 位为 0x3ff,目的是获取页目录表物理地址。中间 10 位为页表的索引,因为是 10 位的索引值,所以这里不用乘以 4。低 12 位为页表内的偏移地址,用来定位页表项,他必须是已经乘以 4 的值

    即为:0x3ff << 22 + 中间10位<<12 + 低12位

三、虚拟地址的转换过程

  • 高 10 位是页目录项 pde 的索引,用于在页目录表中定位 pde,细节是处理器获取高 10 位后自动将其乘以 4,再加上页目录表的物理地址,这样便得到了 pde 索引对应的 pde 所在的物理地址,然后自动在该物理地址中,即该 pde 中,获取保存的页表物理地址
  • 中间 10 位是页表项 pte 的索引,用于在页表中定位 pte。细节是处理器获取中间 10 位后自动将其乘以 4,再加上第一步中得到的页表的物理地址,这样便得到了 pte 索引对应的 pte 所在的物理地址,然后自动在该物理地址(该 pte)中获取保存的普通物理页的物理地址
  • 低 12 位是物理页内的偏移量,页大小是 4KB,12 位可寻址的范围正好是 4KB,因此处理器便直接把低 12 位作为第二步中获取的物理页的偏移量,无需乘以 4。用物理页的物理地址加上这低 12 位的和便是这 32位虚拟地址最终落向的物理地址