处理器所支持的RAM容量受链接到地址总线上的地址管脚数限制。早起Intel处理器从80386到Pentium使用32位物理地址。从理论上讲,这样的系统上可以安装高达4GB的RAM,而实际上,由于用户进程线性地址空间的需要,内核不能直接对1GB以上的RAM进行寻址1。
然而,大型服务器需要大于4GB的RAM来同时运行上千的进程,实际上我们现在的很多计算机的RAM都可能超过这个量级。所有必须扩展32位的80x86结构所支持的RAM容量。实际上即便是使用32位操作系统模拟64位2,也会遇到一些问题,例如高低两个32位的数据同步问题。
物理地址扩展分页机制
Intel通过在它的处理器上把管脚数从32增加到36已经满足了这些需求。从Pentium Pro开始,Intel所有的处理器现在的寻址能力达2^36=64GB.不过,只有引入一种新的分页机制把32位线性地址转换为36位物理地址才能使用所增加的物理地址。
从Pentium Pro处理器开始,Intel引入一种叫做物理地址扩展的机制(Physical Address Extension,PAE),另外一种叫页大小扩展(Page Size Extension,PSE),但Linux并没有采用这种机制。
通过设置cr4控制寄存起中的物理地址扩展(PAE)标志激活PAE。页目录项中的页大小标志PS启动用大尺寸页,在PAE启用时,大小位2MB。当启用了PAE机制之后,系统的分页机制也做了相应的改变:
64GB的RAM被分为2^24个页框,页表项的物理地址字段从20位扩展到了24位,因为PAE页表项必须包含12个标志位和24个物理地址位,总数之和位36,页表项大小从32位变为64位增加了以北,结果一个4KB的页表包含512个表项而不是1024个表项。
引入一个叫做页目录指针表(Page Directory Pointer Table,PDPT)的页表新级别,它由4个64位表项组成。
cr3控制寄存器包含一个27位的页目录指针表(PDPT)基地址字段。因为PDPT存放在RAM的前4GB中,并在32字节的倍数上对齐,因此27位足以表示这种表的基地址。
把线性地址映射到4KB的页时,页目录项中的PS标志清0,32位线性地址按下列方式解释:
| 字段名 | 说明 |
|---|---|
| cr3 | 指向一个PDPT |
| cr3的31-30位 | 指向PDPT中4个项中的一个 |
| cr3的29-21位 | 指向页目录中512个项中的一个 |
| cr3的20-12位 | 指向页表中512项中的一个 |
| cr3的11-0位 | 4KB页中的偏移量 |
当把线性地址隐射到2MB的页时,页目录项中的PS标志为1,32位线性地址按下列方式解释:
| 字段名 | 说明 |
|---|---|
| cr3 | 指向一个PDPT |
| cr3的31-30位 | 指向PDPT中4个项中的一个 |
| cr3的29-21位 | 指向页目录中512个项中的一个 |
| cr3的20-0位 | 2MB页中的偏移量 |
显然,PAE并没有扩大进程的线性地址空间,因为它只能处理物理地址,此外,只有内核能够修改进程的页表,所以用户态下运行的进程不能使用大于4GB的物理地址空间。另一方面,PAE允许内核使用高达64GB的RAM,从而显著增加了系统中的进程数量。
64位系统中的分页
32为处理器普遍采用两级分页3,但是两级分页并不适用于64位计算机系统。
首先假设一个大小为4KB的标准页,因为1KB覆盖2^10个地址范围,4KB覆盖2^12个地址,所以offset字段时12位,这样线性地址就剩下52位分配给Table和Directory
字段。这样可寻址范围非常之大。
如果现在决定使用64位中的48位来寻址,这样寻址范围页可以寻址256T呃空间!如果剩下的48-12=36位将被分配给Table和Directory,如果决定给两个字段各18位,那么每个进程的页目录和页表都含有2^18个项,即256000个项。还是过于庞大。
由于这个原因,所有的64位处理器的硬件分页都使用了额外的分页级别,也就是说多级分页级别。使用的级别数量取决于处理器的类型。不再深入讨论。