分页机制

分页机制的主要目的是高效地利用内存。按页来组织和管理内存空间,把暂时不用的数据放到外部存储器(通常是硬盘)上。在启用分页机制后,操作系统将线性地址划分为固定大小的页面(4KB、2MB或4MB)。每个页可以被映射到物理内存或外部存储器上的虚拟内存文件中。
分页由处理器的控制寄存器的三个标志来控制:
1、PG(分页)标志,CR0寄存器的位31,用于启动分页机制。(从intel386处理器开始的所有intel处理器都有这个标志)
2、PSE(页尺寸拓展)标志,CR4寄存器的位4,启动物理地址拓展,可以最多寻址64GB物理内存,否则最多寻址4GB物理内存。(在Pentium和Pentium Pro处理器中引入)
3、PAE(物理地址拓展)标志,CR4寄存器的位5,用于启用大页面支持,当PAE=1时,大页面为2MB,当PAE=0时,大页面为4MB。(Pentium Pro处理器中引入)

1、页表和页目录

1、页目录

页目录是一个由32位页目录项(page-directory entries,PDEs)组成是数组。每个页目录占一个4KB的内存页,每个PDE的长度为4字节,因此每个页目录中最多包含1024个PDE。
ByoJUI.png
Byo5qJ.png

2、页表

页表是用来存放页表表项(page-table entries:PTEs)的线性表。每个页表占一个4KB的内存页,每个PTE的长度为4字节,每个页表中最多包含1024个PTE。PTE的iao高20位代表的是4KB内存页的起始物理地址的高20位,该起始物理地址的低12位假定为0。
ByH2Gt.png

3、页目录指针表

页目录指针表(page-directory pointer table)包含4个64位的表项,每个表项指向一个页目录,仅用于启用PAE时。启用PAE后,每个PDE和PTE的长度都增大为64位。

2、地址翻译

将32位的虚拟地址翻译为32位的物理地址,其过程可以概括如下:
1、通过CR3寄存器定位到页目录的起始地址。
2、取线性地址的高10位作为索引选取页目录的一个表项(PDE)。
3、根据PDE中的页表基地址(取PDE的高20位,低12位为0)定位到页表。
4、取线性地址的12位到21位作为索引选取页表的一个表项(PTE)。
5、取出PTE中的内存页基地址(PTE的高20位,低12位为0)。
6、取线性地址的低12位作为页中偏移与上一步的内存页基地址相加相加得到物理地址。
Bybgw4.png

3、WinDbg观察分页机制

1、启动计计算器(calc.exe),输入一串数字(如123654)以便后面观察。
2、启动Windbg,附加到计算器程序上开始调试。
3、在Windbg的命令区输入x calc!g*命令列出计算器程序中以g开头的所有符号。
B6jOgA.png

1
01014d90          calc!ghnoNum = <no type information>

4、在Windbg的命令区输入dd calc! gpszNum L1命令,查看该符号地址的内容。

1
01014db0  000c4d60

5、继续查看地址000c4d60处的内容。
BcmFTe.png
可以看到,地址000c4d60处的内容就是我们在计算器中输入的内容(123654)。
6、将字符串地址000c4d60翻译为物理地址。
BcmuOf.png
虚拟地址000c8868的页目录索引(高10位)为0;页表索引(中间10位)为0011 0001 00,即0xC4;
页内偏移为(低12位)1101 0110 0000,即0xD60。
7、查看calc.exe的页目录基地址。
BcmrtJ.png
8、使用!dd命令显示页目录表的内容。
Bcm2X6.png
第一个表项内容为2587d001 ,其高20位为页表的起始地址的高20位,低12(067)位为页表属性。
8、使用!dd命令显示页表的内容。
Bcmh7D.png
高20位为所在内存页的起始地址的高20位,即0x2b37d000,低12位(067)为内存页属性。
9、查看物理地址中的内容。
Bcnm4J.png
BcnuC9.png
可以看到,虚拟地址000c4d60和物理地址2b37dd60中的内容是一致的。