理解内存分页机制

来源:互联网 发布:csdn windows 编辑:程序博客网 时间:2024/04/29 21:16

在8086时期,寄存器是16位,无法存放20位的物理地址,为了解决这问题,人们提出了分段机制,分段机制就是将内存分段,每段大小64kb,在段寄存器中放入段基址,然后+上段偏移量就成了物理地址或者线性地址,为什么说是或呢?因为在采用分页基址的系统中,线性地址加上页偏移量才是真正的物理地址,如果没有用分页机制,计算出来的就是物理地址。


windows NT引入了内存分页机制,此种内存管理机制,使得从应用程序角度来看,其是独占使用4
GB的内存空间,应用程序间内存空间隔离而互不影响,一个进程崩溃不会蔓延、影响到其它进程,另外使得虚拟内存机制成为可能,把暂时不用的内存页交换到磁盘pagefile文件中,需要时再交换进来。
内存分页机制是把物理内存按固定大小分成很多个等份,一般为4K大小,下面也以4K为一页来说明,每个等份称为一页,我称它为物理页,线性地址空间也进行了分页,我称它为线性页,对于某个进程可访问的线性地址空间0~0x3fffffff,如何映射到物理内存中呢?也就是说线性页如何映射到物理页呢?线性页和物理页好像没人如此叫,我来引入一个。下面来探讨一下。
    原来在进程地址空间的0xC0000000起始处的4M空间,到0xC03fffff结束,存放了各个线性页所对应的物理页的物理地址值,每4字节为一项,每1024个项组成一个页表PT,故共1024个PT,页表内的项索引叫PTE(page table entry),如第一个线性页,即0~0x00000fff线性地址空间,其物理页是哪个呢?显然是线性地址0xC0000000指向的DWORD值,依此类推,诙 鱿咝砸常 锢硪澄 咝缘刂?xC0000001的值,线性页映射到物理页后加上页内偏移就可以得到物理地址了,原来挺简单的嘛。
显然页内偏移为线性地址的末尾12位嘛,即有如下公式:
offset=LA && 0x00000fff
LA : 线性地址,line address
offset:页内偏移
PA:物理地址,physic address
理解了前面的描述,易知,线性地址的高20位即为PTE索引
即有PA=*(0xC0000000+LA>>12*4),*表示取地址内容

那0xC0000000开始的4M线性地址,物理页是哪些呢?我们来计算一下
0xC0000000+0xC0000000>>12*4=0xC0300000

可见0xC0300000开始的页表比较特殊,称为页目录表,该表的每一项正好指向一个页表的开始位置,也就是页表的表,页目录表的索引,称为PDE(page directory entry),
假设知道了一个线性地址的PDE,PTE,可按以下公式计算物理地址:
PA = *(0xC0000000+PDE*1024*4+PTE*4)
    = *(0xC0000000+(PDE<<10+PTE)<<2)
对比前面的公式,
*(0xC0000000+LA>>12*4) == *(0xC0000000+(PDE<<10+PTE)<<2)
   LA>>12 == (PDE<<10+PTE)
PDE,PTE最大1024=2的10次方,所以PDE即为线性地址的高10位,PTE为线性地址的中间10
位,线性地址的低12为页内偏移。
有些文章中提到的PDE地址,PTE地址,如何理解?
PDE地址指线性地址在页目录表对应项的地址,
   PDE_add=LA>>22+0xC0300000

PTE地址指线性地址在页表对应项的地址,
   PTE_add=LA>>12+0xC0000000
PTE地址低12位包含了页属性,用windbg可看到
lkd> dt _hardware_PtE
nt!_HARDWARE_PTE
   +0x000 Valid            : Pos 0, 1 Bit
   +0x000 Write            : Pos 1, 1 Bit
   +0x000 Owner            : Pos 2, 1 Bit
   +0x000 WriteThrough     : Pos 3, 1 Bit
   +0x000 CacheDisable     : Pos 4, 1 Bit
   +0x000 Accessed         : Pos 5, 1 Bit
   +0x000 Dirty            : Pos 6, 1 Bit
   +0x000 LargePage        : Pos 7, 1 Bit
   +0x000 Global           : Pos 8, 1 Bit
   +0x000 CopyOnWrite      : Pos 9, 1 Bit
   +0x000 Prototype        : Pos 10, 1 Bit
   +0x000 reserved         : Pos 11, 1 Bit
   +0x000 PageFrameNumber : Pos 12, 20 Bits
   当0位为1时,说明PTE有效,页在物理内存中,而7位的LargePage表示当前虚拟地址大于等于0x80000000并且小于0xa0000000(减去0x80000000就得到了物理地址)
   CPU是如何计算一个线性地址的物理地址的呢?以下参考了一些网上资料。
   1 CR3寄存器保存了当前活动进程的页目录所在物理页地址,CPU通过CR3找到当前页目录所在的物理页地址a
   2 计算PDE的物理地址:a+ 线性地址高10位左移两位 (因为每个页目录项四个字节),取出该地址处的PDE,PDE的前20位+低12位0是这个虚拟地址对应页表的物理地址b
   3 计算PTE的物理地址:b+ 虚拟地址的中间10位左移两位,取出该地址处的PTE,PTE的前20位是这个虚拟地址+低12位0是所对应物理页的地址c
   4 计算该虚拟地址对应的物理地址:c + 虚拟地址最低12位

摘自:http://blog.csdn.net/syf442/archive/2009/07/15/4349748.aspx