浅谈PAE实现原理

文中数字不带单位的话默认bit

32位系统通过物理地址扩展可以使用超过4Gib的物理内存,怎么做到的呢?

众所周知一个32位进程的虚拟地址最多能表示2^20个页表项(页),用虚拟地址里剩下的12bits表示4k的偏移量。其能表示的内存大小上限为2^20*2^12=2^32bit=4Gib

如实际物理内存恰好等于进程中能表示(寻址)的虚拟内存,即物理内存<=4Gib=2^32。一个「页」内偏移2^12(大小4k),需要2^20个「页」表示。相应的页表项里用来寻址的部分(pfn)应该有20bits才能表示完对应到物理内存的2^20个页,和32位虚拟地址空间里最多能表示的页表项个数相同,即虚拟内存刚好可映射到整个物理内存。(上文物理内存里的「页」准确的说是大小和页大小一致且对齐的内存块)

那如果实际物理内存大于进程中能表示(寻址)的虚拟内存,怎么办呢?

CPU增加地址线超过32根的话在硬件层面上就能够寻址大于4Gib的内存了,比如拥有36条地址线的部分32位x86 cpu最大可以支持到64Gib的物理内存(其实这也是无法在其他32位平台上模拟运行使用了PAE的ia32应用/OS的原因,因为那些支持PAE的x86 cpu在硬件上扩展了地址线的数量为36/40/48,而其他32位平台可能真就只有32位的地址线,没法用32位的硬件来模拟寻址36位甚至更大的物理内存空间)。但现在要怎么把OS里的虚拟地址映射到更大的物理地址空间里去呢?


增加页表项里用来寻址的部分的宽度怎么样?

假设我们现在有一根无限大的内存条

一个32位进程的虚拟地址空间里最多还是只能表示2^20个页表项(页),还是用剩下的12bits表示4k的页内偏移量,结果就是虚拟地址空间还是只有2^32这么大。映射的物理地址空间也还是只有2^32=4Gib

但是,因为页表项变长了,可以寻址的物理地址空间增加了(大于虚拟地址空间的4Gib)。或者换句话说,之所以要把页表项增长是为了让虚拟地址能映射到更大的物理地址空间里的任意位置而已。如页表项里用来寻址的部分从20bits增加到40bits的话,可寻址的物理内存空间就是2^40*2^12=2^52这么大了。但是一个32位的进程的虚拟地址空间里还是只有20位来表示页,所以最多只能映射到2^20个页那么大的物理地址空间。所以能表示的物理内存大小是一回事,单个进程的虚拟内存能映射的物理内存是另一回事了。在单个进程的虚拟内存里无法映射到整个物理内存(2^20小于2^40),但是通过特殊的内核机制多个进程的虚拟内存可以映射到物理内存里的不同部分,2^40/2^20=2^20个进程才能完全占满扩展的地址空间。或者单个进程可以通过一些方式(比如win下调用AWE api)把额外的物理内存swap进自己的虚拟地址空间,用完了再swap出去,这里的swap是交换到物理内存里而不是硬盘上的页面文件里。但在同一时刻这个进程可见的内存大小还是只有4Gib。

点击右边的按钮加载评论,如果无法加载那估计是被墙啦..你看着办w