很久没写什么,主要是方便的时候没时间写,有时间写的时候不方便,这不刚好碰上这档事。昨天无意用spy察看偶的crashdump文件时,意外发觉了
一个奇异的地址(0xc0600000),我一直记得是0xc0300000,各位看官表吵(其实这地址就是windows虚拟页目录地址,简称PDE),这东东放的内容就是
页表(简称PTE),Windows就是用此表来map虚拟地址和物理地址。促成写这文的另一个原因是我发现有这样一个贴子,说什么为什么虚表空间不是4M+4K,
唉,真是语不惊人誓不休。
我记得arcsoft一位牛人就喜欢把简单的事用复杂的方法来做,一则体现了实力,二则拥有了声誉,三则害苦了下属。我觉得大多数人在理解页表的时候都是抱着
崇敬的态度,于是本来简单的东东,反而搞复杂了,就象我刚才提到的C030和C060这两个地址一样,可能很多人并不知道怎么来的,那就让老夫来庖丁解牛,
完成这本来应该简单的事。先约定暗号,VA(虚拟地址),PA(物理地址),其它暗号在下文中说明。
开篇入题,Windows的页表是连续的,可以看成一维数组,数组每一项的大小是几字节了?回答是不一定,在32位是4字节,64位是8字节,32位中还有一种
也是8字节,就是所谓的PAE(物理地址扩展),在Windows内核中有定义,_MMPTE(MM不是美眉,是Memory Manangement),先讨论普通4字节,一项
就是4字节,其中高20位对应一个物理页地址,低12位是一些标志,显然低12之所以不用,意味着页大小是12位,那么一页就是2^12=4096=1000h(页大小也
可能变化,万变不离其中),而20位物理页地址(简称PFN,Page frame number),加上12位页大小,刚好是32位,那么总共能访问的内存就是2^32=4G,注意,
这就是32位的极限了,而页表将完整映射对应的4G空间,显示需要4M的页表(2^20 *4),在32位机上,页表的起始地址是0xc0000000,64位机上是0xFFFFF68000000000,
不要以为64位系统现在访问的是64位,非也,仅有48位,也就是前面的四个F,形同虚设(当然以后可能变化)。还记得我最早提到的两个地址吧,看上去怎么有点
缘分,都是C0开头,没错,那两个地址就是页目录地址(PDE),嘛意思,就是这个地址指向的内容,就是页表起始的内容,PA[PDE]=[PTE],也就是PDE放的物理地址
的内容就是PTE虚拟地址的内容,回忆一下,从PTE开始可是映射整个地址空间的,那么PTE自己是不是也有一个,不错,这个对应就是PDE了,算一下看对应地址是多少,
0XC0000000/(页大小 4096)=0xc0000,每一项是4字节,0xc0000*4=0x300000,加上PTE的起始地址,0xc0000000+0x300000=0xc0300000,这不是我最早
提到的地址嘛,如果PTE是8字节了,0xc0000*8 =0x600000,加上PTE,得到0xc0600000,这就是我机上的地址,显示我机上的PTE大小是8字节,从windbg可知,PTE中
PFN为26位,4字节的时候为20位,那么我能用的内存就是2^6 *4G =256G,可惜我现在只有2G,白白浪费这么多的页表空间了。
最后看一下64位的,64位目前只用48位地址,PTE的基地址是0xFFFFF68000000000,注意前面4个F没用,按照刚才的算法,PDE应该是多少了,0xF68000000000/(页大小,4096)=0xF68000000, PTE大小是8字节,0xF68000000*8=0x7B40000000,加上PTE基地址,得到0xFFFFF6FB40000000,在64位中还增加了两个术语,PPE,PXE,PPE放的内容就是PDE,也就是代表PDE的内容,PXE放的就是PPE,放的就是PPE的内容,计算方法不变,真传一句话,当做一维数组,万事皆休矣!