在之前的学习中,有一个课后思考题:10-10-12分页模式物理内存能够识别的最多范围是多少? 我们当时是怎么算的呢?很简单嘛,有1024个页表,每个页表有1024个物理页,每个物理页有4KB,那不就是 1024 * 1024 * 4KB = 4GB 吗?! 答案确实是4GB,但很遗憾,如果你是这样算的,那你对 10-10-12 分页就还没有理解到位。 更有甚者可能会说,32位系统,2^32=4GB,所以寻址范围是4GB,这就更加错的离谱。
实际上,决定物理内存寻址范围的是页表项PTE。
PTE 的低12位是属性;高20位是基址,低12位补零后构成了物理页基址。所以,物理地址的寻址范围是由PTE构成的这32位物理页基址决定的,4GB是从这里来的。
注意,线程的4GB和物理地址寻址范围的4GB不是一个东西。 物理地址寻址的4GB我们刚才已经解释过,是由PTE决定的。而线程的4GB其实指的是32位线性地址确定的,这个才是和32位系统相关的,和分页模式无关,32位系统的线性地址就是32位。
缺点就是物理地址寻址范围太小了,只有4GB。随着硬件的发展,物理内存已经超过4GB了,所以我们需要一种新的分页模式来映射更多的物理内存,2-9-9-12 分页就应运而生了。
先放一张 2-9-9-12分页的结构图,有个印象:
2-9-9-12 分页将物理地址寻址范围扩大到 2^36=64GB。实现方式就是将物理页基址由原来的32位扩大到36位,同时为了内存对齐,PTE整体由原来的4字节扩大到了8字节,下面是PTE结构图:
关于PTE属性,暂时不表,先解释一下 2-9-9-12 这几个数字的含义。
页的大小还是4KB,因此物理页内偏移仍然需要12位,12就是这么来的,和10-10-12的12是一样的意思;由于PTE变成了8字节,因此一个页表只能存 4KB / 8 = 512 个PTE了,512 = 2 ^ 9,第二个9是这么来的;因为物理地址范围已经扩大到64G,所以页表的物理地址可能大于4GB,因此PDE的页表基址也要扩大到36位了,所以页目录表也只能有 512 个PDE了,第一个9是这么来的;32位线性地址,已经用掉了 9+9+12=30位,还剩2位,这两位叫做PDPI(Page-Directory-Point-Index),是PDPT表的下标,2是这么来的。有人可能疑惑说为什么需要PDPT这个表呢?剩下的2位不用不行吗?答:如果不用,那么线性地址就只有30位了,一个进程最多就只能映射1GB的内存了。 如果上面这段解释还有疑问,那你就还没理解进程4GB和物理地址的区别,请从头开始阅读这篇博客,这里确实容易产生混淆,要多花时间理解。
本节课只需要理解到这里就够了,关于PTE的属性,以及PDE和PDPTE,将在下一节课学习。
本文演示XP系统2-9-9-12分页如何将线性地址转换成物理地址。 XP默认分页模式就是 2-9-9-12,如果之前改成了10-10-12,就要先改回来。
[boot loader] timeout=30 default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS [operating systems] multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional[DEBUG]" /noexecute=optin /fastdetect /debug /debugport=com_2 /baudrate=115200 multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=op首先,编写一个程序,定义一个变量,然后打印它的线性地址。
按2-9-9-12分页拆分线性地址
00 PDPI=0 000000000 PDI=0 100101111 PTI=12F 111101100000 物理页偏移:F60查CR3 !process 0 0 CR3=134c03e0
查PDPTE !dq 134c03e0+0 PDPTE=00000000`0e662001 PDT=00e662000
查PDE !dq 00e662000+0 PDE=00000000`0e099067 PTT=00e099000
查PTE !dq 00e099000+12F*8 PTE=80000000`0de5d067 物理页基址=00de5d000
查物理地址 !dd 00de5d000+F60 查到数据是0x12345678,证明成功找到物理地址。
用 !vtop 指令验证:
实验成功。