Win2k内存分页制

 

1.      Win2k内存分页制………………………………………………………………………1

2.      小议WIN NT/2000分页机制…………………………………………………………41

3.      启用PAE后内存分页机制的一点小问题……………………………………………43

4.      使用WinDBG分析启用PAE后的分页机制…………………………………………48

基本概念

    Windows 2000 使用基于分页机制的虚拟内存。每个进程有4GB的虚拟地址空间。基于分页机制,这4GB地址空间的一些部分被映射了物理内存,一些部分映射硬盘上的交换文 件,一些部分什么也没有映射。程序中使用的都是4GB地址空间中的虚拟地址。而访问物理内存,需要使用物理地址。
 
下面我们看看什么是物理地址,什么是虚拟地址。

物 理地址 (physical address): 放在寻址总线上的地址。放在寻址总线上,如果是读,电路根据这个地址每位的值就将相应地址的物理内存中的数据放到数据总线中传输。如果是写,电路根据这个 地址每位的值就将相应地址的物理内存中放入数据总线上的内容。物理内存是以字节(8位)为单位编址的。

虚拟地址 (virtual address): 4G虚拟地址空间中的地址,程序中使用的都是虚拟地址。

如 果CPU寄存器中的分页标志位被设置,那么执行内存操作的机器指令时,CPU会自动根据页目录和页表中的信息,把虚拟地址转换成物理地址,完成该指令。比 如 mov eax,004227b8h ,这是把地址004227b8h处的值赋给寄存器的汇编代码,004227b8这个地址就是虚拟址。CPU在执行这行代码时,发现寄存器中的分页标志位已 经被设定,就自动完成虚拟地址到物理地址的转换,使用物理地址取出值,完成指令。对于Intel CPU 来说,分页标志位是寄存器CR0的第31位,为1表示使用分页,为0表示不使用分页。对于初始化之后的 Win2k 我们观察 CR0 ,发现第31位为1。表明Win2k是使用分页的。

    使用了分页机制之后,4G的地址空间被分成了固定大小的页,每一页或者被映射到物理内存,或者被映射到硬盘上的交换文件中,或者没有映射任何东西。对于一 般程序来说,4G的地址空间,只有一小部分映射了物理内存,大片大片的部分是没有映射任何东西。物理内存也被分页,来映射地址空间。对于32bit的 Win2k,页的大小是4K字节。CPU用来把虚拟地址转换成物理地址的信息存放在叫做页目录和页表的结构里。

    物理内存分页,一个物理页的大小为4K字节,第0个物理页从物理地址 0x00000000 处开始。由于页的大小为4KB,就是0x1000字节,所以第1页从物理地址 0x00001000 处开始。第2页从物理地址 0x00002000 处开始。可以看到由于页的大小是4KB,所以只需要32bit的地址中高20bit来寻址物理页。

    页表,一个页表的大小为4K字节,放在一个物理页中。由1024个4字节的页表项组成。页表项的大小为4个字节(32bit),所以一个页表中有1024 个页表项。页表中的每一项的内容(每项4个字节,32bit)高20bit用来放一个物理页的物理地址,低12bit放着一些标志。

    页目录,一个页目录大小为4K字节,放在一个物理页中。由1024个4字节的页目录项组成。页目录项的大小为4个字节(32bit),所以一个页目录中有 1024个页目录项。页目录中的每一项的内容(每项4个字节)高20bit用来放一个页表(页表放在一个物理页中)的物理地址,低12bit放着一些标 志。

    对于x86系统,页目录的物理地址放在CPU的CR3寄存器中。

    CPU把虚拟地址转换成物理地址:
    一个虚拟地址,大小4个字节(32bit),包含着找到物理地址的信息,分为3个部分:第22位到第31位这10位(最高10位)是页目录中的索引,第 12位到第21位这10位是页表中的索引,第0位到第11位这12位(低12位)是页内偏移。对于一个要转换成物理地址的虚拟地址,CPU首先根据CR3 中的值,找到页目录所在的物理页。然后根据虚拟地址的第22位到第31位这10位(最高的10bit)的值作为索引,找到相应的页目录项 (PDE,page directory entry),页目录项中有这个虚拟地址所对应页表的物理地址。有了页表的物理地址,根据虚拟地址的第12位到第21位这10位的值作为索引,找到该页表 中相应的页表项(PTE,page table entry),页表项中就有这个虚拟地址所对应物理页的物理地址。最后用虚拟地址的最低12位,也就是页内偏移,加上这个物理页的物理地址,就得到了该虚 拟地址所对应的物理地址。

    一个页目录有1024项,虚拟地址最高的10bit刚好可以索引1024项(2的10次方等于1024)。一个页表也有1024项,虚拟地址中间部分的 10bit,刚好索引1024项。虚拟地址最低的12bit(2的12次方等于4096),作为页内偏移,刚好可以索引4KB,也就是一个物理页中的每个 字节。

    一个虚拟地址转换成物理地址的计算过程就是,处理器通过CR3找到当前页目录所在物理页,取虚拟地址的高10bit,然后把这10bit右移2bit(因 为每个页目录项4个字节长,右移2bit相当于乘4)得到在该页中的地址,取出该地址处PDE(4个字节),就找到了该虚拟地址对应页表所在物理页,取虚 拟地址第12位到第21位这10位,然后把这10bit右移2bit(因为每个页表项4个字节长,右移2bit相当于乘4)得到在该页中的地址,取出该地 址处的PTE(4个字节),就找到了该虚拟地址对应物理页的地址,最后加上12bit的页内偏移得到了物理地址。

    32bit的一个指针,可以寻址范围0x00000000-0xFFFFFFFF,4GB大小。也就是说一个32bit的指针可以寻址整个4GB地址空间 的每一个字节。一个页表项负责4K的地址空间和物理内存的映射,一个页表1024项,也就是负责1024*4k=4M的地址空间的映射。一个页目录项,对 应一个页表。一个页目录有1024项,也就对应着1024个页表,每个页表负责4M地址空间的映射。1024个页表负责1024*4M=4G的地址空间映 射。一个进程有一个页目录。所以以页为单位,页目录和页表可以保证4G的地址空间中的每页和物理内存的映射。

    每个进程都有自己的4G地址空间,从 0x00000000-0xFFFFFFFF 。通过每个进程自己的一套页目录和页表来实现。由于每个进程有自己的页目录和页表,所以每个进程的地址空间映射的物理内存是不一样的。两个进程的同一个虚 拟地址处(如果都有物理内存映射)的值一般是不同的,因为他们往往对应不同的物理页。

    4G地址空间中低2G,0x00000000-0x7FFFFFFF 是用户地址空间,4G地址空间中高2G,
0x80000000-0xFFFFFFFF 是系统地址空间。访问系统地址空间需要程序有ring0的权限。

进程的页目录和页表在虚拟地址空间中的位置

    当执行一条访问内存的指令时,如果寄存器中的分页标志位已经被设置,CPU就自动完成虚拟 地址到物理地址的转换,来完成该指令。CPU在转换地址过程中,并不需要页目录和页表的虚拟地址。但是分页标志位被设置之后,CPU会把所有指令中的地址 当做虚拟地址转换成物理地址。所以程序中使用的都是虚拟地址。一个进程的页表和页目录是由系统维护的,比如一个进程申请或者释放内存,系统就需要设置对应 的一些页表项。系统需要访问页目录和页表,但是系统只能使用虚拟地址,所以系统必须把页目录和页表映射到地址空间中。对应4G地址空间的1024个页表被 顺序映射到了从0xC0000000到0xC03FFFFF的4M地址空间。对应第一个4M地址空间的页表,被映射到了0xC0000000开始的第一个 4K地址空间(0xC0000000开始的4K)。对应第二个4M地址空间的页表,被映射到了0xC0000000开始的第二个4K地址空间 (0xC0001000开始的4K),以此类推。页目录被映射到了0xC0300000开始处的4K地址空间。0xC0000000到 0xC03FFFFF的4M地址空间位于高2G的系统地址空间内,需要ring0的权限才能访问。

有效页目录项和有效页表项

    页目录项和页表项的最低位,第0位,指明了一页是否映射了物理内存。最低位为1,有效 (Valid),表示该页映射了物理内存。页目录项和页表项,4个字节,32bit,有着差不多的结构。使用 Win2k DDK 所附带的内核调试器,Kernel Debugger (KD) ,我们可以得到有效的页目录项和页表项的结构定义,对于使用 X86 CPU 的系统,该结构定义如下

!strct HARDWARE_PTE_X86
struct _HARDWARE_PTE_X86 (sizeof=4)
+0 bits0-0 Valid
+0 bits1-1 Write
+0 bits2-2 Owner
+0 bits3-3 WriteThrough
+0 bits4-4 CacheDisable
+0 bits5-5 Accessed
+0 bits6-6 Dirty
+0 bits7-7 LargePage
+0 bits8-8 Global
+0 bits9-9 CopyOnWrite
+0 bits10-10 Prototype
+0 bits11-11 reserved
+0 bits12-31 PageFrameNumber

bits12-31 PageFrameNumber:
页 目录项或者页表项的第12到第31位,长20位。物理页的页帧号。(将这32位和0xFFFFF000做与运算,就得到了该4KB物理页第一个字节的地 址)由于页的大小是4KB,所以只需要20位,就可以寻址4G大小范围内的每一页。对于页目录项来说,所得的物理页中放着的是一个页表。

bits0-0 Valid: 
为0无效,该页没有映射物理内存。为1有效。该页映射了物理内存。

bits1-1 Write:
为0该页只读。为1该页可以读写。

bits2-2 Owner:
为0访问该页需要ring0权限,只有核心态(kernel-mode)的代码才可以访问。
为1访问该页ring3权限就可以,用户态(user-mode)代码就可以访问。

bits3-3 WriteThrough:
为0 对相关页使用 write-back caching 策略。为1 对相关页使用 write-through caching 策略。
直 写式(Write-through),在CPU向Cache写入的同时,也把数据写入相应内存单元。保证Cache和内存中相应单元数据的一致性。直写式 速度慢,而且有些操作是不必要的,比如CPU连续多次更新一个Cache单元的内容,将导致相应内存单元连续多次被写入,而效果其实和写入最后一次更新是 一样的。
回写式(Write-back),CPU修改了Cache的内容后,并不立即修改内存中相应的单元。只有当回写操作被执行的时候,才修改相应内存单元。比如该Cache单元的内容从Cache中撤销时触发回写操作。回写式速度快,也避免了一些不必要的操作。
如果CR0中的CD (cache disable)标志为1,则处理器忽略WriteThrough标志。CD标志,CR0寄存器的第30bit
。观察发现,初始化之后的Win2k中,该位为0。也就是说页目录项和页表项中的WriteThrough标志是起作用的。

bits4-4 CacheDisable:
为0 允许Cache该页。为1 禁止Cache该页。
如果CR0中的CD (cache disable)标志为1,则处理器忽略CacheDisable标志。CD标志,CR0寄存器的第30bit
。观察发现,初始化之后的Win2k中,该位为0。也就是说页目录项和页表项中的CacheDisable标志是起作用的。

bits5-5 Accessed:
为0 该页没有被访问(读出或者写入)过。为1 该页被访问(读出或者写入)过。

bits6-6 Dirty:
为0 该页中的内容没有被改动过。 为1 该页中的内容已经被改动过了(被写过)。

bits7-7 LargePage:
为0 表示页大小为4K,为1 表示页大小为4M。

bits8-8 Global:
为0 表示不是 global page。为1 表示是一个 global page。
如 果CR4中的 page global enable (PGE) 标志为1 ,表示允许 page global,那么当进程转换时在 TLB(Translation lookaside buffer ) 高速缓存中的 global page 不会失效。用来防止常用页(比如内核或者操作系统的执行代码所在页)被换出TLB高速缓存。寄存器CR4的PGE标志是第7位。观察发现,初始化之后的 Win2k中,该位为1。

bits9-9 CopyOnWrite:
用于 Copy-on-Write 机制。

bits10-10 Prototype:
用于 进程间内存共享 机制。

bits11-11 reserved:
保留


页目录和页表

    我们可以使用 SoftICE 获得指定进程的页目录,方法如下,首先不加参数的 addr 命令,将列出当前系统中的进程。然后 addr 进程名 ,切换到该进程的地址空间。然后 dd c0300000 l 1000 ,将会在命令窗口输出0xc0300000处的0x1000字节(16进制,也就是4K字节)。然后退出 SoftICE,使用 Symbol Loader 的菜单中的 File -> Save SoftICE History AS.. 就可以把刚才输出的内容保存到文件中。每个进程的页目录都映射到了0xc0300000处,所以我们就得到了页目录的内容。

我也写了一个叫 JiurlPdPtSee 的程序,可以输出指定进程的页目录和页表。以下的内容就来自这个程序。

打开的一个记事本进程的页目录:

c0300000: 05f5b067 058ae067 067b5067 00eae067
c0300010: 03bfa067 00000000 00000000 00000000
c0300020: 00000000 00000000 00000000 00000000
c0300030: 00000000 00000000 00000000 00000000
c0300040: 00000000 00000000 00000000 00000000
c0300050: 00000000 00000000 00000000 00000000
c0300060: 00000000 00000000 00000000 00000000
c0300070: 00000000 00000000 00000000 00000000
c0300080: 00000000 00000000 00000000 00000000
c0300090: 00000000 00000000 00000000 00000000
c03000a0: 00000000 00000000 00000000 00000000
c03000b0: 00000000 00000000 00000000 00000000
c03000c0: 00000000 00000000 00000000 00000000
c03000d0: 00000000 00000000 00000000 00000000
c03000e0: 00000000 00000000 00000000 00000000
c03000f0: 00000000 00000000 00000000 00000000
c0300100: 043b1067 00000000 00000000 00000000
c0300110: 00000000 00000000 00000000 00000000
c0300120: 00000000 00000000 00000000 00000000
c0300130: 00000000 00000000 00000000 00000000
c0300140: 00000000 00000000 00000000 00000000
c0300150: 00000000 00000000 00000000 00000000
c0300160: 00000000 00000000 00000000 00000000
c0300170: 00000000 00000000 00000000 00000000
c0300180: 00000000 00000000 00000000 00000000
c0300190: 00000000 00000000 00000000 00000000
c03001a0: 00000000 00000000 00000000 00000000
c03001b0: 00000000 00000000 00000000 00000000
c03001c0: 00000000 00000000 00000000 00000000
c03001d0: 00000000 00000000 00000000 00000000
c03001e0: 00000000 00000000 00000000 00000000
c03001f0: 00000000 00000000 00000000 00000000
c0300200: 00000000 00000000 00000000 00000000
c0300210: 00000000 00000000 00000000 00000000
c0300220: 00000000 00000000 00000000 00000000
c0300230: 00000000 00000000 00000000 00000000
c0300240: 00000000 00000000 00000000 00000000
c0300250: 00000000 00000000 00000000 00000000
c0300260: 00000000 00000000 00000000 00000000
c0300270: 00000000 00000000 00000000 00000000
c0300280: 00000000 00000000 00000000 00000000
c0300290: 00000000 00000000 00000000 00000000
c03002a0: 00000000 00000000 00000000 00000000
c03002b0: 00000000 00000000 00000000 00000000
c03002c0: 00000000 00000000 00000000 00000000
c03002d0: 00000000 00000000 00000000 00000000
c03002e0: 00000000 00000000 00000000 00000000
c03002f0: 00000000 00000000 00000000 00000000
c0300300: 00000000 00000000 00000000 00000000
c0300310: 00000000 00000000 00000000 00000000
c0300320: 00000000 00000000 00000000 00000000
c0300330: 00000000 00000000 00000000 00000000
c0300340: 00000000 00000000 00000000 00000000
c0300350: 00000000 00000000 00000000 00000000
c0300360: 00000000 00000000 00000000 00000000
c0300370: 00000000 00000000 00000000 00000000
c0300380: 00000000 00000000 00000000 00000000
c0300390: 00000000 00000000 00000000 00000000
c03003a0: 00000000 00000000 00000000 00000000
c03003b0: 00000000 00000000 00000000 00000000
c03003c0: 00000000 00000000 00000000 00000000
c03003d0: 00000000 00000000 00000000 00000000
c03003e0: 00000000 00000000 00000000 00000000
c03003f0: 00000000 00000000 00000000 00000000
c0300400: 00000000 00000000 00000000 00000000
c0300410: 00000000 00000000 00000000 00000000
c0300420: 00000000 00000000 00000000 00000000
c0300430: 00000000 00000000 00000000 00000000
c0300440: 00000000 00000000 00000000 00000000
c0300450: 00000000 00000000 00000000 00000000
c0300460: 00000000 00000000 00000000 00000000
c0300470: 00000000 00000000 00000000 00000000
c0300480: 00000000 00000000 00000000 00000000
c0300490: 00000000 00000000 00000000 00000000
c03004a0: 00000000 00000000 00000000 00000000
c03004b0: 00000000 00000000 00000000 00000000
c03004c0: 00000000 00000000 00000000 00000000
c03004d0: 00000000 00000000 00000000 00000000
c03004e0: 00000000 00000000 00000000 00000000
c03004f0: 00000000 00000000 00000000 00000000
c0300500: 00000000 00000000 00000000 00000000
c0300510: 00000000 00000000 00000000 00000000
c0300520: 00000000 00000000 00000000 00000000
c0300530: 00000000 00000000 00000000 00000000
c0300540: 00000000 00000000 00000000 00000000
c0300550: 00000000 00000000 00000000 00000000
c0300560: 00000000 00000000 00000000 00000000
c0300570: 00000000 00000000 00000000 00000000
c0300580: 00000000 00000000 00000000 00000000
c0300590: 00000000 00000000 00000000 00000000
c03005a0: 00000000 00000000 00000000 00000000
c03005b0: 00000000 00000000 00000000 00000000
c03005c0: 00000000 00000000 00000000 00000000
c03005d0: 00000000 00000000 00000000 00000000
c03005e0: 00000000 00000000 00000000 00000000
c03005f0: 00000000 00000000 00000000 00000000
c0300600: 00000000 00000000 00000000 00000000
c0300610: 00000000 00000000 00000000 00000000
c0300620: 00000000 00000000 00000000 00000000
c0300630: 00000000 00000000 00000000 00000000
c0300640: 00000000 00000000 00000000 00000000
c0300650: 00000000 00000000 00000000 00000000
c0300660: 00000000 00000000 00000000 00000000
c0300670: 00000000 00000000 00000000 00000000
c0300680: 00000000 00000000 00000000 00000000
c0300690: 00000000 00000000 00000000 00000000
c03006a0: 00000000 00000000 00000000 00000000
c03006b0: 00000000 00000000 00000000 00000000
c03006c0: 00000000 00000000 00000000 00000000
c03006d0: 00000000 00000000 00000000 0423a067
c03006e0: 00000000 00000000 00000000 00000000
c03006f0: 00000000 00000000 00000000 00000000
c0300700: 00000000 00000000 00000000 00000000
c0300710: 00000000 00000000 00000000 00000000
c0300720: 00000000 00000000 00000000 00000000
c0300730: 00000000 00000000 00000000 00000000
c0300740: 00000000 00000000 00000000 00000000
c0300750: 00000000 00000000 00000000 0154b067
c0300760: 00000000 00000000 01fa4067 00000000
c0300770: 00000000 03946067 06825067 00d00067
c0300780: 01cc7067 00000000 00000000 00000000
c0300790: 00000000 00000000 00000000 00000000
c03007a0: 00000000 00000000 00000000 00000000
c03007b0: 00000000 00000000 00000000 00000000
c03007c0: 00000000 00000000 00000000 00000000
c03007d0: 00000000 00000000 00000000 00000000
c03007e0: 00000000 00000000 00000000 00000000
c03007f0: 00000000 02869067 00000000 07b98067
c0300800: 000001e3 004001e3 008001e3 00c001e3
c0300810: 010001e3 014001e3 018001e3 01c001e3
c0300820: 020001e3 024001e3 028001e3 02c001e3
c0300830: 030001e3 034001e3 038001e3 03c001e3
c0300840: 040001e3 044001e3 048001e3 04c001e3
c0300850: 050001e3 054001e3 058001e3 05c001e3
c0300860: 060001e3 064001e3 068001e3 06c001e3
c0300870: 070001e3 074001e3 078001e3 07c001e3
c0300880: 080001e3 084001e3 088001e3 08c001e3
c0300890: 090001e3 094001e3 098001e3 09c001e3
c03008a0: 0a0001e3 0a4001e3 0a8001e3 0ac001e3
c03008b0: 0b0001e3 0b4001e3 0b8001e3 0bc001e3
c03008c0: 0c0001e3 0c4001e3 0c8001e3 0cc001e3
c03008d0: 0d0001e3 0d4001e3 0d8001e3 0dc001e3
c03008e0: 0e0001e3 0e4001e3 0e8001e3 0ec001e3
c03008f0: 0f0001e3 0f4001e3 0f8001e3 0fc001e3
c0300900: 100001e3 104001e3 108001e3 10c001e3
c0300910: 110001e3 114001e3 118001e3 11c001e3
c0300920: 120001e3 124001e3 128001e3 12c001e3
c0300930: 130001e3 134001e3 138001e3 13c001e3
c0300940: 140001e3 144001e3 148001e3 14c001e3
c0300950: 150001e3 154001e3 158001e3 15c001e3
c0300960: 160001e3 164001e3 168001e3 16c001e3
c0300970: 170001e3 174001e3 178001e3 17c001e3
c0300980: 180001e3 184001e3 188001e3 18c001e3
c0300990: 190001e3 194001e3 198001e3 19c001e3
c03009a0: 1a0001e3 1a4001e3 1a8001e3 1ac001e3
c03009b0: 1b0001e3 1b4001e3 1b8001e3 1bc001e3
c03009c0: 1c0001e3 1c4001e3 1c8001e3 1cc001e3
c03009d0: 1d0001e3 1d4001e3 1d8001e3 1dc001e3
c03009e0: 1e0001e3 1e4001e3 1e8001e3 1ec001e3
c03009f0: 1f0001e3 1f4001e3 1f8001e3 1fc001e3
c0300a00: 06470163 00000000 00000000 00000000
c0300a10: 00000000 00000000 00000000 00000000
c0300a20: 00000000 00000000 00000000 00000000
c0300a30: 00000000 00000000 00000000 00000000
c0300a40: 016f1163 016f2163 016f3163 016f4163
c0300a50: 016f5163 016f6163 016d7163 016d8163
c0300a60: 016d9163 016da163 016db163 016dc163
c0300a70: 016dd163 016de163 016df163 01740163
c0300a80: 01701163 01702163 01703163 01704163
c0300a90: 01705163 01706163 01707163 01708163
c0300aa0: 01709163 0170a163 0170b163 0170c163
c0300ab0: 0170d163 0170e163 0170f163 01710163
c0300ac0: 01711163 01712163 01713163 01714163
c0300ad0: 01715163 01716163 016f7163 016f8163
c0300ae0: 016f9163 016fa163 016fb163 016fc163
c0300af0: 016fd163 016fe163 016ff163 01760163
c0300b00: 01721163 01722163 01723163 01724163
c0300b10: 01725163 01726163 01727163 01728163
c0300b20: 01729163 0172a163 0172b163 0172c163
c0300b30: 0172d163 0172e163 0172f163 01730163
c0300b40: 01731163 01732163 01733163 01734163
c0300b50: 01735163 01736163 01717163 01718163
c0300b60: 01719163 0171a163 0171b163 0171c163
c0300b70: 0171d163 0171e163 0171f163 01780163
c0300b80: 01741163 01742163 01743163 01744163
c0300b90: 01745163 01746163 01747163 01748163
c0300ba0: 01749163 0174a163 0174b163 0174c163
c0300bb0: 0174d163 0174e163 0174f163 01750163
c0300bc0: 01751163 01752163 01753163 01754163
c0300bd0: 01755163 01756163 01737163 01738163
c0300be0: 01739163 0173a163 0173b163 0173c163
c0300bf0: 0173d163 0173e163 0173f163 017a0163
c0300c00: 05cf0063 04a11063 00000000 01670163
c0300c10: 01671163 01672163 01673163 01674163
c0300c20: 01675163 01676163 01657163 01658163
c0300c30: 01659163 0165a163 0165b163 0165c163
c0300c40: 0165d163 0165e163 0165f163 016c0163
c0300c50: 01681163 01682163 01683163 01684163
c0300c60: 01685163 01686163 01687163 01688163
c0300c70: 01689163 0168a163 0168b163 0168c163
c0300c80: 0168d163 0168e163 0168f163 01690163
c0300c90: 01691163 01692163 01693163 01694163
c0300ca0: 01695163 01696163 01677163 01678163
c0300cb0: 01679163 0167a163 0167b163 0167c163
c0300cc0: 0167d163 0167e163 0167f163 016e0163
c0300cd0: 016a1163 016a2163 016a3163 016a4163
c0300ce0: 016a5163 016a6163 016a7163 016a8163
c0300cf0: 016a9163 016aa163 016ab163 016ac163
c0300d00: 016ad163 016ae163 016af163 016b0163
c0300d10: 016b1163 016b2163 016b3163 016b4163
c0300d20: 016b5163 016b6163 01697163 01698163
c0300d30: 01699163 0169a163 0169b163 0169c163
c0300d40: 0169d163 0169e163 0169f163 01700163
c0300d50: 016c1163 016c2163 016c3163 016c4163
c0300d60: 016c5163 016c6163 016c7163 016c8163
c0300d70: 016c9163 016ca163 016cb163 016cc163
c0300d80: 016cd163 016ce163 016cf163 016d0163
c0300d90: 016d1163 016d2163 016d3163 016d4163
c0300da0: 016d5163 016d6163 016b7163 016b8163
c0300db0: 016b9163 016ba163 016bb163 016bc163
c0300dc0: 016bd163 016be163 016bf163 01720163
c0300dd0: 016e1163 016e2163 016e3163 016e4163
c0300de0: 016e5163 016e6163 016e7163 016e8163
c0300df0: 016e9163 016ea163 016eb163 016ec163
c0300e00: 016ed163 016ee163 016ef163 016f0163
c0300e10: 01765163 026f6163 05189163 055ab163
c0300e20: 00000000 0740f163 05a71163 05f43163
c0300e30: 0090a163 0297e163 04867163 00000000
c0300e40: 00000000 00000000 00000000 00000000
c0300e50: 00000000 00000000 00000000 00000000
c0300e60: 00000000 00000000 00000000 00000000
c0300e70: 00000000 00000000 01768163 01769163
c0300e80: 0176a163 0176b163 0176c163 0176d163
c0300e90: 0176e163 0176f163 01770163 01771163
c0300ea0: 01772163 01773163 01774163 01775163
c0300eb0: 01776163 01757163 01758163 01759163
c0300ec0: 0175a163 0175b163 0175c163 0175d163
c0300ed0: 0175e163 0175f163 017c0163 01781163
c0300ee0: 01782163 01783163 01784163 01785163
c0300ef0: 01786163 01787163 01788163 01789163
c0300f00: 0178a163 01000163 01001163 01002163
c0300f10: 01003163 01004163 01005163 01006163
c0300f20: 01007163 01008163 01009163 0100a163
c0300f30: 0100b163 0100c163 0100d163 0100e163
c0300f40: 0100f163 01010163 01011163 01012163
c0300f50: 01013163 01014163 01015163 01016163
c0300f60: 01017163 01018163 01019163 0101a163
c0300f70: 0101b163 0101c163 0101d163 0101e163
c0300f80: 0101f163 01020163 01021163 01022163
c0300f90: 01023163 01024163 01025163 01026163
c0300fa0: 01027163 01028163 01029163 0102a163
c0300fb0: 0102b163 0102c163 0102d163 0102e163
c0300fc0: 0102f163 01030163 01031163 01032163
c0300fd0: 01033163 01034163 01035163 01036163
c0300fe0: 01037163 01038163 01039163 0103a163
c0300ff0: 0103b163 0103c163 0103d163 00031163

我们来分析一下这个页目录。
4G 地址空间,低2G是用户空间,前512项页目录项用于这2G的地址转换。高2G是系统空间,后512项页目录项用于这2G的地址转换。每项32bit,第 0bit是有效位,该位为0表示没有该项所对应的虚拟地址空间的页表。在前512项中我们看到了大量的00000000,最低位为0,表示这些项都没有页 表。也就是说这项对应的4MB地址空间是没有物理内存映射的。我们看到了在用户地址空间中有大量的页是没有物理页的映射的,什么映射也没有是空的。我们再 看另外一个进程的页目录,然后和这个做比较。

System 进程的页目录:

c0300000: 01860067 00000000 00000000 00000000
c0300010: 00000000 00000000 00000000 00000000
c0300020: 00000000 00000000 00000000 00000000
c0300030: 00000000 00000000 00000000 00000000
c0300040: 00000000 00000000 00000000 00000000
c0300050: 00000000 00000000 00000000 00000000
c0300060: 00000000 00000000 00000000 00000000
c0300070: 00000000 00000000 00000000 00000000
c0300080: 00000000 00000000 00000000 00000000
c0300090: 00000000 00000000 00000000 00000000
c03000a0: 00000000 00000000 00000000 00000000
c03000b0: 00000000 00000000 00000000 00000000
c03000c0: 00000000 00000000 00000000 00000000
c03000d0: 00000000 00000000 00000000 00000000
c03000e0: 00000000 00000000 00000000 00000000
c03000f0: 00000000 00000000 00000000 00000000
c0300100: 00000000 00000000 00000000 00000000
c0300110: 00000000 00000000 00000000 00000000
c0300120: 00000000 00000000 00000000 00000000
c0300130: 00000000 00000000 00000000 00000000
c0300140: 00000000 00000000 00000000 00000000
c0300150: 00000000 00000000 00000000 00000000
c0300160: 00000000 00000000 00000000 00000000
c0300170: 00000000 00000000 00000000 00000000
c0300180: 00000000 00000000 00000000 00000000
c0300190: 00000000 00000000 00000000 00000000
c03001a0: 00000000 00000000 00000000 00000000
c03001b0: 00000000 00000000 00000000 00000000
c03001c0: 00000000 00000000 00000000 00000000
c03001d0: 00000000 00000000 00000000 00000000
c03001e0: 00000000 00000000 00000000 00000000
c03001f0: 00000000 00000000 00000000 00000000
c0300200: 00000000 00000000 00000000 00000000
c0300210: 00000000 00000000 00000000 00000000
c0300220: 00000000 00000000 00000000 00000000
c0300230: 00000000 00000000 00000000 00000000
c0300240: 00000000 00000000 00000000 00000000
c0300250: 00000000 00000000 00000000 00000000
c0300260: 00000000 00000000 00000000 00000000
c0300270: 00000000 00000000 00000000 00000000
c0300280: 00000000 00000000 00000000 00000000
c0300290: 00000000 00000000 00000000 00000000
c03002a0: 00000000 00000000 00000000 00000000
c03002b0: 00000000 00000000 00000000 00000000
c03002c0: 00000000 00000000 00000000 00000000
c03002d0: 00000000 00000000 00000000 00000000
c03002e0: 00000000 00000000 00000000 00000000
c03002f0: 00000000 00000000 00000000 00000000
c0300300: 00000000 00000000 00000000 00000000
c0300310: 00000000 00000000 00000000 00000000
c0300320: 00000000 00000000 00000000 00000000
c0300330: 00000000 00000000 00000000 00000000
c0300340: 00000000 00000000 00000000 00000000
c0300350: 00000000 00000000 00000000 00000000
c0300360: 00000000 00000000 00000000 00000000
c0300370: 00000000 00000000 00000000 00000000
c0300380: 00000000 00000000 00000000 00000000
c0300390: 00000000 00000000 00000000 00000000
c03003a0: 00000000 00000000 00000000 00000000
c03003b0: 00000000 00000000 00000000 00000000
c03003c0: 00000000 00000000 00000000 00000000
c03003d0: 00000000 00000000 00000000 00000000
c03003e0: 00000000 00000000 00000000 00000000
c03003f0: 00000000 00000000 00000000 00000000
c0300400: 00000000 00000000 00000000 00000000
c0300410: 00000000 00000000 00000000 00000000
c0300420: 00000000 00000000 00000000 00000000
c0300430: 00000000 00000000 00000000 00000000
c0300440: 00000000 00000000 00000000 00000000
c0300450: 00000000 00000000 00000000 00000000
c0300460: 00000000 00000000 00000000 00000000
c0300470: 00000000 00000000 00000000 00000000
c0300480: 00000000 00000000 00000000 00000000
c0300490: 00000000 00000000 00000000 00000000
c03004a0: 00000000 00000000 00000000 00000000
c03004b0: 00000000 00000000 00000000 00000000
c03004c0: 00000000 00000000 00000000 00000000
c03004d0: 00000000 00000000 00000000 00000000
c03004e0: 00000000 00000000 00000000 00000000
c03004f0: 00000000 00000000 00000000 00000000
c0300500: 00000000 00000000 00000000 00000000
c0300510: 00000000 00000000 00000000 00000000
c0300520: 00000000 00000000 00000000 00000000
c0300530: 00000000 00000000 00000000 00000000
c0300540: 00000000 00000000 00000000 00000000
c0300550: 00000000 00000000 00000000 00000000
c0300560: 00000000 00000000 00000000 00000000
c0300570: 00000000 00000000 00000000 00000000
c0300580: 00000000 00000000 00000000 00000000
c0300590: 00000000 00000000 00000000 00000000
c03005a0: 00000000 00000000 00000000 00000000
c03005b0: 00000000 00000000 00000000 00000000
c03005c0: 00000000 00000000 00000000 00000000
c03005d0: 00000000 00000000 00000000 00000000
c03005e0: 00000000 00000000 00000000 00000000
c03005f0: 00000000 00000000 00000000 00000000
c0300600: 00000000 00000000 00000000 00000000
c0300610: 00000000 00000000 00000000 00000000
c0300620: 00000000 00000000 00000000 00000000
c0300630: 00000000 00000000 00000000 00000000
c0300640: 00000000 00000000 00000000 00000000
c0300650: 00000000 00000000 00000000 00000000
c0300660: 00000000 00000000 00000000 00000000
c0300670: 00000000 00000000 00000000 00000000
c0300680: 00000000 00000000 00000000 00000000
c0300690: 00000000 00000000 00000000 00000000
c03006a0: 00000000 00000000 00000000 00000000
c03006b0: 00000000 00000000 00000000 00000000
c03006c0: 00000000 00000000 00000000 00000000
c03006d0: 00000000 00000000 00000000 00000000
c03006e0: 00000000 00000000 00000000 00000000
c03006f0: 00000000 00000000 00000000 00000000
c0300700: 00000000 00000000 00000000 00000000
c0300710: 00000000 00000000 00000000 00000000
c0300720: 00000000 00000000 00000000 00000000
c0300730: 00000000 00000000 00000000 00000000
c0300740: 00000000 00000000 00000000 00000000
c0300750: 00000000 00000000 00000000 00000000
c0300760: 00000000 00000000 00000000 00000000
c0300770: 00000000 00000000 00000000 02119067
c0300780: 00000000 00000000 00000000 00000000
c0300790: 00000000 00000000 00000000 00000000
c03007a0: 00000000 00000000 00000000 00000000
c03007b0: 00000000 00000000 00000000 00000000
c03007c0: 00000000 00000000 00000000 00000000
c03007d0: 00000000 00000000 00000000 00000000
c03007e0: 00000000 00000000 00000000 00000000
c03007f0: 00000000 00000000 00000000 02138067
c0300800: 000001e3 004001e3 008001e3 00c001e3
c0300810: 010001e3 014001e3 018001e3 01c001e3
c0300820: 020001e3 024001e3 028001e3 02c001e3
c0300830: 030001e3 034001e3 038001e3 03c001e3
c0300840: 040001e3 044001e3 048001e3 04c001e3
c0300850: 050001e3 054001e3 058001e3 05c001e3
c0300860: 060001e3 064001e3 068001e3 06c001e3
c0300870: 070001e3 074001e3 078001e3 07c001e3
c0300880: 080001e3 084001e3 088001e3 08c001e3
c0300890: 090001e3 094001e3 098001e3 09c001e3
c03008a0: 0a0001e3 0a4001e3 0a8001e3 0ac001e3
c03008b0: 0b0001e3 0b4001e3 0b8001e3 0bc001e3
c03008c0: 0c0001e3 0c4001e3 0c8001e3 0cc001e3
c03008d0: 0d0001e3 0d4001e3 0d8001e3 0dc001e3
c03008e0: 0e0001e3 0e4001e3 0e8001e3 0ec001e3
c03008f0: 0f0001e3 0f4001e3 0f8001e3 0fc001e3
c0300900: 100001e3 104001e3 108001e3 10c001e3
c0300910: 110001e3 114001e3 118001e3 11c001e3
c0300920: 120001e3 124001e3 128001e3 12c001e3
c0300930: 130001e3 134001e3 138001e3 13c001e3
c0300940: 140001e3 144001e3 148001e3 14c001e3
c0300950: 150001e3 154001e3 158001e3 15c001e3
c0300960: 160001e3 164001e3 168001e3 16c001e3
c0300970: 170001e3 174001e3 178001e3 17c001e3
c0300980: 180001e3 184001e3 188001e3 18c001e3
c0300990: 190001e3 194001e3 198001e3 19c001e3
c03009a0: 1a0001e3 1a4001e3 1a8001e3 1ac001e3
c03009b0: 1b0001e3 1b4001e3 1b8001e3 1bc001e3
c03009c0: 1c0001e3 1c4001e3 1c8001e3 1cc001e3
c03009d0: 1d0001e3 1d4001e3 1d8001e3 1dc001e3
c03009e0: 1e0001e3 1e4001e3 1e8001e3 1ec001e3
c03009f0: 1f0001e3 1f4001e3 1f8001e3 1fc001e3
c0300a00: 06470163 06f15163 00000000 00000000
c0300a10: 00000000 00000000 00000000 00000000
c0300a20: 00000000 00000000 00000000 00000000
c0300a30: 00000000 00000000 00000000 00000000
c0300a40: 016f1163 016f2163 016f3163 016f4163
c0300a50: 016f5163 016f6163 016d7163 016d8163
c0300a60: 016d9163 016da163 016db163 016dc163
c0300a70: 016dd163 016de163 016df163 01740163
c0300a80: 01701163 01702163 01703163 01704163
c0300a90: 01705163 01706163 01707163 01708163
c0300aa0: 01709163 0170a163 0170b163 0170c163
c0300ab0: 0170d163 0170e163 0170f163 01710163
c0300ac0: 01711163 01712163 01713163 01714163
c0300ad0: 01715163 01716163 016f7163 016f8163
c0300ae0: 016f9163 016fa163 016fb163 016fc163
c0300af0: 016fd163 016fe163 016ff163 01760163
c0300b00: 01721163 01722163 01723163 01724163
c0300b10: 01725163 01726163 01727163 01728163
c0300b20: 01729163 0172a163 0172b163 0172c163
c0300b30: 0172d163 0172e163 0172f163 01730163
c0300b40: 01731163 01732163 01733163 01734163
c0300b50: 01735163 01736163 01717163 01718163
c0300b60: 01719163 0171a163 0171b163 0171c163
c0300b70: 0171d163 0171e163 0171f163 01780163
c0300b80: 01741163 01742163 01743163 01744163
c0300b90: 01745163 01746163 01747163 01748163
c0300ba0: 01749163 0174a163 0174b163 0174c163
c0300bb0: 0174d163 0174e163 0174f163 01750163
c0300bc0: 01751163 01752163 01753163 01754163
c0300bd0: 01755163 01756163 01737163 01738163
c0300be0: 01739163 0173a163 0173b163 0173c163
c0300bf0: 0173d163 0173e163 0173f163 017a0163
c0300c00: 00030067 01520063 00000000 01670163
c0300c10: 01671163 01672163 01673163 01674163
c0300c20: 01675163 01676163 01657163 01658163
c0300c30: 01659163 0165a163 0165b163 0165c163
c0300c40: 0165d163 0165e163 0165f163 016c0163
c0300c50: 01681163 01682163 01683163 01684163
c0300c60: 01685163 01686163 01687163 01688163
c0300c70: 01689163 0168a163 0168b163 0168c163
c0300c80: 0168d163 0168e163 0168f163 01690163
c0300c90: 01691163 01692163 01693163 01694163
c0300ca0: 01695163 01696163 01677163 01678163
c0300cb0: 01679163 0167a163 0167b163 0167c163
c0300cc0: 0167d163 0167e163 0167f163 016e0163
c0300cd0: 016a1163 016a2163 016a3163 016a4163
c0300ce0: 016a5163 016a6163 016a7163 016a8163
c0300cf0: 016a9163 016aa163 016ab163 016ac163
c0300d00: 016ad163 016ae163 016af163 016b0163
c0300d10: 016b1163 016b2163 016b3163 016b4163
c0300d20: 016b5163 016b6163 01697163 01698163
c0300d30: 01699163 0169a163 0169b163 0169c163
c0300d40: 0169d163 0169e163 0169f163 01700163
c0300d50: 016c1163 016c2163 016c3163 016c4163
c0300d60: 016c5163 016c6163 016c7163 016c8163
c0300d70: 016c9163 016ca163 016cb163 016cc163
c0300d80: 016cd163 016ce163 016cf163 016d0163
c0300d90: 016d1163 016d2163 016d3163 016d4163
c0300da0: 016d5163 016d6163 016b7163 016b8163
c0300db0: 016b9163 016ba163 016bb163 016bc163
c0300dc0: 016bd163 016be163 016bf163 01720163
c0300dd0: 016e1163 016e2163 016e3163 016e4163
c0300de0: 016e5163 016e6163 016e7163 016e8163
c0300df0: 016e9163 016ea163 016eb163 016ec163
c0300e00: 016ed163 016ee163 016ef163 016f0163
c0300e10: 01765163 026f6163 05189163 055ab163
c0300e20: 059ad163 0740f163 05a71163 05f43163
c0300e30: 0090a163 0297e163 04867163 034ae163
c0300e40: 00000300 00000300 00000300 00000300
c0300e50: 00000300 00000300 00000300 00000300
c0300e60: 00000300 00000300 00000300 00000300
c0300e70: 00000300 00000300 01768163 01769163
c0300e80: 0176a163 0176b163 0176c163 0176d163
c0300e90: 0176e163 0176f163 01770163 01771163
c0300ea0: 01772163 01773163 01774163 01775163
c0300eb0: 01776163 01757163 01758163 01759163
c0300ec0: 0175a163 0175b163 0175c163 0175d163
c0300ed0: 0175e163 0175f163 017c0163 01781163
c0300ee0: 01782163 01783163 01784163 01785163
c0300ef0: 01786163 01787163 01788163 01789163
c0300f00: 0178a163 01000163 01001163 01002163
c0300f10: 01003163 01004163 01005163 01006163
c0300f20: 01007163 01008163 01009163 0100a163
c0300f30: 0100b163 0100c163 0100d163 0100e163
c0300f40: 0100f163 01010163 01011163 01012163
c0300f50: 01013163 01014163 01015163 01016163
c0300f60: 01017163 01018163 01019163 0101a163
c0300f70: 0101b163 0101c163 0101d163 0101e163
c0300f80: 0101f163 01020163 01021163 01022163
c0300f90: 01023163 01024163 01025163 01026163
c0300fa0: 01027163 01028163 01029163 0102a163
c0300fb0: 0102b163 0102c163 0102d163 0102e163
c0300fc0: 0102f163 01030163 01031163 01032163
c0300fd0: 01033163 01034163 01035163 01036163
c0300fe0: 01037163 01038163 01039163 0103a163
c0300ff0: 0103b163 0103c163 0103d163 00031163

我们再来分析。
这是系统进程的页目录。首先在用户地址空间中,是大片的没有物理内存映射。
然 后我们用UltraEdit把两个页目录做比较。发现两个进程的用户地址空间(低2G,前512项)中没有同一位置的有效项,这说明了,每个进程有自己独 立的用户地址空间,各自映射不同的物理内存。而系统地址空间(高2G,后512项)的比较结果是绝大部分项的内容是一样的。页目录项一样的话,该项对应的 页表,将在同一个物理页上,也就是页表肯定也是同一个。那么页表相应的物理页也就是同一个。说明两个进程的系统地址空间中绝大部分内容是一样的。 c0300c00处的页目录项对应的是,页表和页目录所在的4M地址空间,每个进程的页目录和页表的内容不同,所以他们当然在不同的物理页,比较的结果也 是不同的。

我们再来看看页表中的内容,我们选择的是刚才那个记事本进程的页目录中的页目录项1(页目录内偏移+4处的页目录项)对应的页表。

记事本进程页目录项1对应的页表:

c0001000: 00000000 00000000 00000000 00000000
c0001010: 00000000 00000000 00000000 00000000
c0001020: 00000000 00000000 00000000 00000000
c0001030: 00000000 00000000 0464f025 046dd025
c0001040: 00000000 00000000 00000000 00000000
c0001050: 00000000 00000000 00000000 00000000
c0001060: 00000000 00000000 00000000 00000000
c0001070: 00000000 00000000 00000000 00000000
c0001080: 00000000 00000000 00000000 00000000
c0001090: 00000000 00000000 00000000 00000000
c00010a0: 00000000 00000000 00000000 00000000
c00010b0: 00000000 00000000 00000000 00000000
c00010c0: 00000000 00000000 00000000 00000000
c00010d0: 00000000 00000000 00000000 00000000
c00010e0: 00000000 00000000 00000000 00000000
c00010f0: 00000000 00000000 00000000 00000000
c0001100: 00000000 00000000 00000000 00000000
c0001110: 00000000 00000000 00000000 00000000
c0001120: 00000000 00000000 00000000 00000000
c0001130: 00000000 00000000 00000000 00000000
c0001140: 00000000 00000000 00000000 00000000
c0001150: 00000000 00000000 00000000 00000000
c0001160: 00000000 00000000 00000000 00000000
c0001170: 00000000 00000000 00000000 00000000
c0001180: 00000000 00000000 00000000 00000000
c0001190: 00000000 00000000 00000000 00000000
c00011a0: 00000000 00000000 00000000 00000000
c00011b0: 00000000 00000000 00000000 00000000
c00011c0: 00000000 00000000 00000000 00000000
c00011d0: 00000000 00000000 00000000 00000000
c00011e0: 00000000 00000000 00000000 00000000
c00011f0: 00000000 00000000 00000000 00000000
c0001200: 00000000 00000000 00000000 00000000
c0001210: 00000000 00000000 00000000 00000000
c0001220: 00000000 00000000 00000000 00000000
c0001230: 00000000 00000000 00000000 00000000
c0001240: 00000000 00000000 00000000 00000000
c0001250: 00000000 00000000 00000000 00000000
c0001260: 00000000 00000000 00000000 00000000
c0001270: 00000000 00000000 00000000 00000000
c0001280: 00000000 00000000 00000000 00000000
c0001290: 00000000 00000000 00000000 00000000
c00012a0: 00000000 00000000 00000000 00000000
c00012b0: 00000000 00000000 00000000 00000000
c00012c0: 00000000 00000000 00000000 00000000
c00012d0: 00000000 00000000 00000000 00000000
c00012e0: 00000000 00000000 00000000 00000000
c00012f0: 00000000 00000000 00000000 00000000
c0001300: 00000000 00000000 00000000 00000000
c0001310: 00000000 00000000 00000000 00000000
c0001320: 00000000 00000000 00000000 00000000
c0001330: 00000000 00000000 00000000 00000000
c0001340: 00000000 00000000 00000000 00000000
c0001350: 00000000 00000000 00000000 00000000
c0001360: 00000000 00000000 00000000 00000000
c0001370: 00000000 00000000 00000000 00000000
c0001380: 00000000 00000000 00000000 00000000
c0001390: 00000000 00000000 00000000 00000000
c00013a0: 00000000 00000000 00000000 00000000
c00013b0: 00000000 00000000 00000000 00000000
c00013c0: 00000000 00000000 00000000 00000000
c00013d0: 00000000 00000000 00000000 00000000
c00013e0: 00000000 00000000 00000000 00000000
c00013f0: 00000000 00000000 00000000 00000000
c0001400: 00000000 00000000 00000000 00000000
c0001410: 00000000 00000000 00000000 00000000
c0001420: 00000000 00000000 00000000 00000000
c0001430: 00000000 00000000 00000000 00000000
c0001440: 00000000 00000000 00000000 00000000
c0001450: 00000000 00000000 00000000 00000000
c0001460: 00000000 00000000 00000000 00000000
c0001470: 00000000 00000000 00000000 00000000
c0001480: 00000000 00000000 00000000 00000000
c0001490: 00000000 00000000 00000000 00000000
c00014a0: 00000000 00000000 00000000 00000000
c00014b0: 00000000 00000000 00000000 00000000
c00014c0: 00000000 00000000 00000000 00000000
c00014d0: 00000000 00000000 00000000 00000000
c00014e0: 00000000 00000000 00000000 00000000
c00014f0: 00000000 00000000 00000000 00000000
c0001500: 00000000 00000000 00000000 00000000
c0001510: 00000000 00000000 00000000 00000000
c0001520: 00000000 00000000 00000000 00000000
c0001530: 00000000 00000000 00000000 00000000
c0001540: 00000000 00000000 00000000 00000000
c0001550: 00000000 00000000 00000000 00000000
c0001560: 00000000 00000000 00000000 00000000
c0001570: 00000000 00000000 00000000 00000000
c0001580: 00000000 00000000 00000000 00000000
c0001590: 00000000 00000000 00000000 00000000
c00015a0: 00000000 00000000 00000000 00000000
c00015b0: 00000000 00000000 00000000 00000000
c00015c0: 00000000 00000000 00000000 00000000
c00015d0: 00000000 00000000 00000000 00000000
c00015e0: 00000000 00000000 00000000 00000000
c00015f0: 00000000 00000000 00000000 00000000
c0001600: 00000000 00000000 00000000 00000000
c0001610: 00000000 00000000 00000000 00000000
c0001620: 00000000 00000000 00000000 00000000
c0001630: 00000000 00000000 00000000 00000000
c0001640: 00000000 00000000 00000000 00000000
c0001650: 00000000 00000000 00000000 00000000
c0001660: 00000000 00000000 00000000 00000000
c0001670: 00000000 00000000 00000000 00000000
c0001680: 00000000 00000000 00000000 00000000
c0001690: 00000000 00000000 00000000 00000000
c00016a0: 00000000 00000000 00000000 00000000
c00016b0: 00000000 00000000 00000000 00000000
c00016c0: 00000000 00000000 00000000 00000000
c00016d0: 00000000 00000000 00000000 00000000
c00016e0: 00000000 00000000 00000000 00000000
c00016f0: 00000000 00000000 00000000 00000000
c0001700: 00000000 00000000 00000000 00000000
c0001710: 00000000 00000000 00000000 00000000
c0001720: 00000000 00000000 00000000 00000000
c0001730: 00000000 00000000 00000000 00000000
c0001740: 00000000 00000000 00000000 00000000
c0001750: 00000000 00000000 00000000 00000000
c0001760: 00000000 00000000 00000000 00000000
c0001770: 00000000 00000000 00000000 00000000
c0001780: 00000000 00000000 00000000 00000000
c0001790: 00000000 00000000 00000000 00000000
c00017a0: 00000000 00000000 00000000 00000000
c00017b0: 00000000 00000000 00000000 00000000
c00017c0: 00000000 00000000 00000000 00000000
c00017d0: 00000000 00000000 00000000 00000000
c00017e0: 00000000 00000000 00000000 00000000
c00017f0: 00000000 00000000 00000000 00000000
c0001800: 00000000 00000000 00000000 00000000
c0001810: 00000000 00000000 00000000 00000000
c0001820: 00000000 00000000 00000000 00000000
c0001830: 00000000 00000000 00000000 00000000
c0001840: 00000000 00000000 00000000 00000000
c0001850: 00000000 00000000 00000000 00000000
c0001860: 00000000 00000000 00000000 00000000
c0001870: 00000000 00000000 00000000 00000000
c0001880: 00000000 00000000 00000000 00000000
c0001890: 00000000 00000000 00000000 00000000
c00018a0: 00000000 00000000 00000000 00000000
c00018b0: 00000000 00000000 00000000 00000000
c00018c0: 00000000 00000000 00000000 00000000
c00018d0: 00000000 00000000 00000000 00000000
c00018e0: 00000000 00000000 00000000 00000000
c00018f0: 00000000 00000000 00000000 00000000
c0001900: 00000000 00000000 00000000 00000000
c0001910: 00000000 00000000 00000000 00000000
c0001920: 00000000 00000000 00000000 00000000
c0001930: 00000000 00000000 00000000 00000000
c0001940: 00000000 00000000 00000000 00000000
c0001950: 00000000 00000000 00000000 00000000
c0001960: 00000000 00000000 00000000 00000000
c0001970: 00000000 00000000 00000000 00000000
c0001980: 00000000 00000000 00000000 00000000
c0001990: 00000000 00000000 00000000 00000000
c00019a0: 00000000 00000000 00000000 00000000
c00019b0: 00000000 00000000 00000000 00000000
c00019c0: 00000000 00000000 00000000 00000000
c00019d0: 00000000 00000000 00000000 00000000
c00019e0: 00000000 00000000 00000000 00000000
c00019f0: 00000000 00000000 00000000 00000000
c0001a00: 00000000 00000000 00000000 00000000
c0001a10: 00000000 00000000 00000000 00000000
c0001a20: 00000000 00000000 00000000 00000000
c0001a30: 00000000 00000000 00000000 00000000
c0001a40: 00000000 00000000 00000000 00000000
c0001a50: 00000000 00000000 00000000 00000000
c0001a60: 00000000 00000000 00000000 00000000
c0001a70: 00000000 00000000 00000000 00000000
c0001a80: 01fd8067 00000000 00000000 00000000
c0001a90: 00000000 00000000 00000000 00000000
c0001aa0: 00000000 00000000 00000000 00000000
c0001ab0: 00000000 00000000 00000000 00000000
c0001ac0: 02ed9047 00000000 00000000 00000000
c0001ad0: 00000000 00000000 00000000 00000000
c0001ae0: 00000000 00000000 00000000 00000000
c0001af0: 00000000 00000000 00000000 00000000
c0001b00: 05d3c047 0243d047 006de047 0217f047
c0001b10: 04f39047 0695a047 01c5b047 00000000
c0001b20: 00000000 00000000 00000000 00000000
c0001b30: 00000000 00000000 00000000 00000000
c0001b40: 07596005 07597005 00000000 00000000
c0001b50: 00000000 00000000 00000000 00000000
c0001b60: 00000000 00000000 00000000 00000000
c0001b70: 00000000 00000000 00000000 00000000
c0001b80: 0272a047 00000000 00000000 00000000
c0001b90: 00000000 00000000 00000000 00000000
c0001ba0: 00000000 00000000 00000000 00000000
c0001bb0: 00000000 00000000 00000000 00000000
c0001bc0: 06825047 00000000 00000000 00000000
c0001bd0: 00000000 00000000 00000000 00000000
c0001be0: 00000000 00000000 00000000 00000000
c0001bf0: 00000000 00000000 00000000 00000000
c0001c00: 00000000 00000000 00000000 00000000
c0001c10: 00000000 00000000 00000000 00000000
c0001c20: 00000000 00000000 00000000 00000000
c0001c30: 00000000 00000000 00000000 00000000
c0001c40: 00000000 00000000 00000000 00000000
c0001c50: 00000000 00000000 00000000 00000000
c0001c60: 00000000 00000000 00000000 00000000
c0001c70: 00000000 00000000 00000000 00000000
c0001c80: 00000000 00000000 00000000 00000000
c0001c90: 00000000 00000000 00000000 00000000
c0001ca0: 00000000 00000000 00000000 00000000
c0001cb0: 00000000 00000000 00000000 00000000
c0001cc0: 00000000 00000000 00000000 00000000
c0001cd0: 00000000 00000000 00000000 00000000
c0001ce0: 00000000 00000000 00000000 00000000
c0001cf0: 00000000 00000000 00000000 00000000
c0001d00: 00000000 00000000 00000000 00000000
c0001d10: 00000000 00000000 00000000 00000000
c0001d20: 00000000 00000000 00000000 00000000
c0001d30: 00000000 00000000 00000000 00000000
c0001d40: 00000000 00000000 00000000 00000000
c0001d50: 00000000 00000000 00000000 00000000
c0001d60: 00000000 00000000 00000000 00000000
c0001d70: 00000000 00000000 00000000 00000000
c0001d80: 00000000 00000000 00000000 00000000
c0001d90: 00000000 00000000 00000000 00000000
c0001da0: 00000000 00000000 00000000 00000000
c0001db0: 00000000 00000000 00000000 00000000
c0001dc0: 04daf047 03c90047 05ba1047 03de2047
c0001dd0: 00000000 00000000 00000000 00000000
c0001de0: 00000000 00000000 00000000 00000000
c0001df0: 00000000 00000000 00000000 00000000
c0001e00: 00ef1047 052d2047 05573047 065f4047
c0001e10: 01c55047 03a56047 03457047 045b8047
c0001e20: 076d9047 037ba047 04f3b047 0347c047
c0001e30: 033dd047 05a1e047 01dbf047 02220047
c0001e40: 00000000 00000000 00000000 00000000
c0001e50: 00000000 00000000 00000000 00000000
c0001e60: 00000000 00000000 00000000 00000000
c0001e70: 00000000 00000000 00000000 00000000
c0001e80: 00000000 00000000 00000000 00000000
c0001e90: 00000000 00000000 00000000 00000000
c0001ea0: 00000000 00000000 00000000 00000000
c0001eb0: 00000000 00000000 00000000 00000000
c0001ec0: 00000000 00000000 00000000 00000000
c0001ed0: 00000000 00000000 00000000 00000000
c0001ee0: 00000000 00000000 00000000 00000000
c0001ef0: 00000000 00000000 00000000 00000000
c0001f00: 00000000 00000000 00000000 00000000
c0001f10: 00000000 00000000 00000000 00000000
c0001f20: 00000000 00000000 00000000 00000000
c0001f30: 00000000 00000000 00000000 00000000
c0001f40: 00000000 00000000 00000000 00000000
c0001f50: 00000000 00000000 00000000 00000000
c0001f60: 00000000 00000000 00000000 00000000
c0001f70: 00000000 00000000 00000000 00000000
c0001f80: 00000000 00000000 00000000 00000000
c0001f90: 00000000 00000000 00000000 00000000
c0001fa0: 00000000 00000000 00000000 00000000
c0001fb0: 00000000 00000000 00000000 00000000
c0001fc0: 00000000 00000000 00000000 00000000
c0001fd0: 00000000 00000000 00000000 00000000
c0001fe0: 00000000 00000000 00000000 00000000
c0001ff0: 00000000 00000000 00000000 00000000

分析一下这个页表,一个页表负责4MB地址空间。每个有效项表明该页被映射到了物理页。从这个页表中看到,有大量的项是没有物理页映射的。这4MB地址空间,只有一部分映射了物理内存。


地址空间中的 Large Page 部分

    在页目录中我们可以看到从0xC0300800到0xC03009FC这128个页目录项的低12位值为0x1e3,也就是 111100011 。这些项的第7位, LargePage标志位,为1,表明这128个页目录项所指的是128个4M页。这128项所对应的虚拟地址空间 0x80000000 - 0x9FFFFFFF,大小0x20000000 Bytes = 512 M Bytes。

    对于 x86 CPU 来说,要支持同时处理4K页目录项和4M页目录项,需要 寄存器CR4中的PSE标志为1,寄存器CR4的第4位是PSE标志。观察Win2k发现寄存器CR4中的PSE标志值为1,表明了Win2k的可以同时混用4M页和4K页。

kd> r cr4
r cr4
cr4=000002d1

    对于4M的页目录项来说,它的第22bit到第31bit,这高10bit指明一个4M页的物理地址,第12bit到第21bit这10bit必须为0。 最低12bit仍然是那些标志。对于4K的页目录项,它所指的物理页中放着一个页表。而对于4M的页目录项,它所指的物理页是直接用来放代码和数据的。也 就是说该项不再需要页表了。CPU进行虚拟地址到物理地址的转换时,使用高10bit作为在页目录中的索引,找到页目录项,发现页目录项的 Large Page 标志位被设置的话,就直接取出该项中的物理地址,然后用虚拟地址的低22bit作为页内偏移,得到物理地址。

    系统的核心模组一般比较大,而系统的核心模组会经常使用,所以他们的页表项放在TLB(Translation Look-Aside Buffer)高速缓存中比较好,如果使用4K页,需要多个4K页,也就需要占用比较多的TLB高速缓存。TLB高速缓存是非常宝贵的资源,如果使用4M 页的话,那么就可以节省很多TLB高速缓存。

    实际中Win2k的两个最重要的核心模组 hal.dll 和 ntoskrnl.exe 被放在这片4M页的地址空间中。

    观察这128个页目录项中的物理地址,就会发现 地址空间 80000000 - 9FFFFFFF 将和物理内存 00000000 - 1FFFFFFF 一一映射。比如我有128M物理内存,他们将全部映射在这个地址空间中。从有效标志位来看,这128个页目录项,都是有效的。而且实际上他们总是有效的。 他们对应512M的地址空间。如果只有128M的物理内存的话,明显很大一部分实际上不会有物理内存映射的。没有物理内存映射,而页目录项指示有效,那么 读这些地址的内存,将会怎样?结果是不会蓝屏,读会成功完成,读出来的所有内容都是FF。

    如果这128个页目录项不是4M的页目录项,而是4K的页目录项的话,将会对应128个页表。那么现在这128个页表,从C0200000开始的128个 页表,也就是 C0200000 - C027FFFF 这 512K 的地址空间是什么内容呢?观察结果是他们这128页中,映射了和128个页目录项对应4M地址空间的第一个4K相同的内容。比如,地址C0200000的 这4K和地址80000000的4K内容是一样的,都是物理地址为00000000的4K。地址C0201000的这4K和地址80400000的4K内 容是一样的,都是物理地址为00400000的4K。

    关于80000000-9FFFFFFF 将和物理内存 00000000-1FFFFFFF 一一映射。而且这128个页目录项总是有效的。
    我们也可以在 ntoskrnl!MmGetPhysicalAddress 函数中找到证据。MmGetPhysicalAddress,将指定的虚拟地址转换成物理地址,参数介绍可以看ddk。这是个很简单的函数,用 SoftICE在这个函数上下断点,然后自己写个驱动程序,用不同范围的虚拟地址触发这个函数。用SoftICE跟一遍这个函数的执行过程。就会发现对于 在80000000-9FFFFFFF 中的地址,根本没做有效性检查,说明了他们总是有效的。而虚拟地址到物理地址的转换方法说明了和物理内存 00000000-1FFFFFFF 一一映射。其实计算在这个范围之内的虚拟地址对应的物理地址,只需要用虚拟地址减去0x80000000。

下面是使用 kd 反汇编函数 MmGetPhysicalAddress 得到的输出
u MmGetPhysicalAddress l 30
ntoskrnl!MmGetPhysicalAddress:
804374e0 56 push esi
804374e1 8b742408 mov esi,[esp+0x8]
804374e5 33d2 xor edx,edx
804374e7 81fe00000080 cmp esi,0x80000000
804374ed 722c jb ntoskrnl!MmGetPhysicalAddress+0x2b (8043751b)
804374ef 81fe000000a0 cmp esi,0xa0000000
804374f5 7324 jnb ntoskrnl!MmGetPhysicalAddress+0x2b (8043751b)
804374f7 39153ce74780 cmp [ntoskrnl!MmKseg2Frame (8047e73c)],edx
804374fd 741c jz ntoskrnl!MmGetPhysicalAddress+0x2b (8043751b)
804374ff 8bc6 mov eax,esi
80437501 c1e80c shr eax,0xc
80437504 25ffff0100 and eax,0x1ffff
80437509 6a0c push 0xc
8043750b 59 pop ecx
8043750c e8d3a7fcff call ntoskrnl!_allshl (80401ce4)
80437511 81e6ff0f0000 and esi,0xfff
80437517 03c6 add eax,esi
80437519 eb17 jmp ntoskrnl!MmGetPhysicalAddress+0x57 (80437532)
8043751b 8bc6 mov eax,esi
8043751d c1e80a shr eax,0xa
80437520 25fcff3f00 and eax,0x3ffffc
80437525 2d00000040 sub eax,0x40000000
8043752a 8b00 mov eax,[eax]
8043752c a801 test al,0x1
8043752e 7506 jnz ntoskrnl!MmGetPhysicalAddress+0x44 (80437536)
80437530 33c0 xor eax,eax
80437532 5e pop esi
80437533 c20400 ret 0x4
80437536 c1e80c shr eax,0xc
80437539 ebce jmp ntoskrnl!MmGetPhysicalAddress+0x47 (80437509)
8043753b cc int 3

8种转换

由于页表被映射到了0xc0000000 开始的4MB地址空间。
所以我们也可以象CPU那样完成虚拟地址到物理地址的转换。

系统按照对应虚拟空间的先后顺序,把一个进程的页表映射在0xc0000000 开始的4MB地址空间中,把页目录映射在0xc0300000 开始的4KB地址空间中。于是我们可以做如下几种地址的相互转换。

1 虚拟地址->虚拟地址对应的PDE地址

PDE_Address=(VirtualAddress>>22)*4+0xC0300000 

2 虚拟地址->虚拟地址对应的PTE地址

PTE_Address=(VirtualAddress>>12)*4+0xC0000000 

3 虚拟地址->物理地址

如果 虚拟地址大于等于0x80000000 并且小于0xa0000000(在 Large Page 部分),
直接用虚拟地址减去0x80000000就得到了物理地址。
其他情况
取得该虚拟地址的PDE,判断是否有效。
有效的话,取得该虚拟地址的PTE,判断是否有效。
有效的话,将PTE的低12位清0加上虚拟地址的低12位就得到了物理地址。
由于页表和页目录在系统地址空间中,访问需要程序运行在ring0,所以要测试的话,需要写驱动程序。

unsigned int PDE;
unsigned int PTE;

if(VirtualAddress>=0x80000000 && VirtualAddress<0xa0000000)
{
PhysicalAddress=VirtualAddress-0x80000000;
}
else
{
PDE=*(unsigned int*)((VirtualAddress>>22)*4+0xC0300000);
if(PDE&0x00000001)
{
PTE=*(unsigned int*)((VirtualAddress>>12)*4+0xC0000000);
if(PTE&0x00000001)
{
PhysicalAddress=((PTE&0xFFFFF000)+(VirtualAddress&0x00000FFF));
}
}
}

4 一个PDE的地址->相应的虚拟地址范围

VirtualAddressStart=((PDE_Address-0xC0300000)/4)<<22
VirtualAddressEnd=VirtualAddressStart+0x003FFFFF

5 一个PTE的地址->相应的虚拟地址范围

VirtualAddressStart=((PTE_Address-0xC0000000)/4)<<12
VirtualAddressEnd=VirtualAddressStart+0x00000FFF

6 物理地址->虚拟地址

一 个物理地址常常会对应多个虚拟地址。转换方法就是遍历所有页表和页目录,如果有效就比较该项的高20bit是否等于我们提供的物理地址的高20bit,如 果相等,就找到了一个。比如该项是第i个PDE的,第j个PTE,那么虚拟地址等于,i*4M+j*4K+物理地址的低12bit。遍历所有页表和页目录 找到每一个。

7 一个PTE的地址->相应PDE的地址

一个PTE的地址可以找到相应的虚拟地址范围,就可以找到虚拟地址对应的PDE地址
PDE_Address=(VirtualAddress>>22)*4+0xC0300000 
PDE_Address=((((PTE_Address-0xC0000000)/4)<<12)>>22)*4+0xC0300000 

8 一个PDE的地址->相应PTE的地址范围

一个PDE的地址可以找到相应的虚拟地址范围的开始地址,就可以找到该虚拟地址对应的PTE地址,
一个PDE对应1024个PTE,4K大小。

PTE_AddressStart=(VirtualAddress>>12)*4+0xC0000000
PTE_AddressStart=((((PDE_Address-0xC0300000)/4)<<22)>>12)*4+0xC0000000 
PTE_AddressEnd=PTE_AddressStart+0x00000FFF

无效页与 Page Fault

访 问的虚拟地址所在页在物理内存中时,该虚拟地址所在页相应的 PDE,PTE 都有效,CPU 自动根据相应的PDE,PTE把虚拟地址转换成物理地址,完成访问。一个虚拟地址所在页不在物理内存中时,比如在硬盘上的交换文件中,该虚拟地址所在页相 应的 PDE,PTE 都无效,访问该虚拟地址将引起 Page-Fault 异常(Exception)。从而使 CPU 转去执行异常处理程序,异常处理程序会做相应的处理。对于发现访问的虚拟地址所在的页在硬盘上的交换文件中,就从交换文件中读入该页到物理内存,重新使 PTE有效,并指向正确的物理页。最后 CPU 重新执行引起异常的指令,这时该指令所访问的虚拟地址已经在物理内存中了,并且该虚拟地址的PTE也有效了,于是就可以顺利执行。

下面我们针对 x86 CPU 做更详细的说明。

当 某条指令访问无效页时,比如指令 MOV EAX,InValidAddress ,执行这条指令时,CPU 会自动通过页目录和页表把虚拟地址 InValidAddress 转换成物理地址,在地址转换过程中,CPU 在从页表项得到物理页地址的同时,会进行页保护检查,比如看该页表项是否有效,是否是只读等等。当CPU发现指令中地址的页表项无效,就会引发异常 (Exception)。异常也是由 CPU 实现的。这里引起的是一个 Page Fault 异常,它的中断号是 0xe (十进制14),需要注意的是 Page Fault 的中断号是 0xe 这是由 CPU 定义的( x86 CPU 的 从 0 - 31 这32个中断是由 CPU 定义的,CPU 将根据这个定义做相应工作)。在发生异常时,CPU 自动把一些寄存器压入堆栈,然后根据中断号,(通过IDTR寄存器找到中断描述符表)在中断描述符表中找到相应的中断描述符,根据中断描述符中的地址,转 到异常处理程序。中断描述符是由Win2k设置,异常处理程序也是由Win2k决定。对于 Win2k Build 2195 来说,中断 0xe 的处理程序是 ntoskrnl!KiTrap0E 地址在 804648a4 。当转到KiTrap0E 时,CPU 已经在堆栈中压入了下面的内容

|-------------| 
|    EFLAGS   |
|-------------|
|      CS     |
|-------------|
|     EIP     |
|-------------|
|  Error Code |
|-------------|<---- [ ESP ]


page-fault 异常 (#PF) 的 Error Code 定义如下( CPU 定义 )
                                   |  3 | 2 | 1 | 0 |
+---------------------------------------------------+ 
|          Reserved                |RSVD|U/S|R/W| P |
+---------------------------------------------------+ 

P   0 错误由无效页引起
    1 错误由违反页保护引起
W/R 0 引起错误的内存访问是读
    1 引起错误的内存访问是写
U/S 0 访问错误时处理器处在管理模式
    1 访问错误时处理器处在用户模式

需要说明的是堆栈中压入的 EIP 就是引发异常的指令地址,将来将根据这个地址重新执行该指令。而寄存器 cr2 中是引发异常时访问的地址。

#PF 异常处理程序 KiTrap0E(由Win2k提供)将会调用 ntoskrnl!MmAccessFault ,MmAccessFault 通过 CR2 中的访问地址,计算出相应的 PDE,PTE地址,通过分析PTE中的内容,可以知道是哪种情况引起的异常,并根据情况作出相应的处理。

当 发生异常时,CPU会把一些寄存器压入堆栈,转到相应的异常处理程序(由Win2k提供),Win2k 在异常处理程序中又会把一些寄存器压入堆栈,最后会在堆栈中形成一个 KTRAP_FRAME 结构。这个 KTRAP_FRAME 是 ntoskrnl!MmAccessFault 的参数之一。

!strct KTRAP_FRAME
struct _KTRAP_FRAME (sizeof=140)
+00 uint32 DbgEbp
+04 uint32 DbgEip
+08 uint32 DbgArgMark
+0c uint32 DbgArgPointer
+10 uint32 TempSegCs
+14 uint32 TempEsp
+18 uint32 Dr0
+1c uint32 Dr1
+20 uint32 Dr2
+24 uint32 Dr3
+28 uint32 Dr6
+2c uint32 Dr7
+30 uint32 SegGs
+34 uint32 SegEs
+38 uint32 SegDs
+3c uint32 Edx
+40 uint32 Ecx
+44 uint32 Eax
+48 uint32 PreviousPreviousMode
+4c struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList
+50 uint32 SegFs
+54 uint32 Edi
+58 uint32 Esi
+5c uint32 Ebx
+60 uint32 Ebp
+64 uint32 ErrCode
+68 uint32 Eip
+6c uint32 SegCs
+70 uint32 EFlags
+74 uint32 HardwareEsp
+78 uint32 HardwareSegSs
+7c uint32 V86Es
+80 uint32 V86Ds
+84 uint32 V86Fs
+88 uint32 V86Gs

系统,CPU 与 页目录项,页表项的关系

一个进程的PDE(页目录项),PTE(页表项)是由系统维护的。地址转换由CPU自动完成。访问无效地址CPU 将产生异常,执行异常处理程序。异常处理程序是系统提供的。

对 于有效的 PDE,PTE,他们的格式大部分由CPU定义,CPU 将按照这个格式,根据每一位的值,决定相应的处理方式。CPU 利用这个格式中自己定义的物理页物理地址的部分来进行地址转换,自己定义的一些标志位来实现页的保护。系统必须按照这个格式定义,来维护 PDE 和 PTE。

x86 CPU 的有效页表项,CPU 定义如下

struct _HARDWARE_PTE_X86 (sizeof=4)
bits0-0 Valid
bits1-1 Write
bits2-2 Owner
bits3-3 WriteThrough
bits4-4 CacheDisable
bits5-5 Accessed
bits6-6 Dirty
bits7-7 LargePage
bits8-8 Global
bits9-11 reserved
bits12-31 PageFrameNumber

其中要注意的是 bits9-11 reserved 这3位,CPU 没有定义,留给操作系统使用。

对于无效的 PDE,PTE,他们的格式大部分由系统定义。当 CPU 发现访问的 PDE,PTE 无效时,就会转去执行异常处理程序。异常处理程序是由系统提供的。系统将按照自己定义的格式,根据每一位的值,决定相应的处理方式。

x86 CPU 的无效页表项,CPU 定义如下

struct _HARDWARE_PTE_X86 (sizeof=4)
bits0-0 Valid
bits1-31 reserved

对于无效页来说,CPU只定义了bits0-0,用来判断是否有效。无效页的 bits0-0 值为0。其他位都留给操作系统使用。

 

为什么地址空间的大小是4G


    使用32bit的cpu话,处理32bit的数据比较好。这就决定了在代码中将被非常频繁使用的地址是32bit的。而32bit的地址可以寻址的范围是 从0x00000000 到 0xFFFFFFFF ,也就是4GB(对于以字节为单位的编址)大小的范围。也就决定了地址空间的大小是 4G。


为什么一页的大小是4K(只是我个人的看法)

    确定了虚拟地址空间的大小之后,又决定使用分页来进行内存管理。权衡把虚拟地址转换成物理地址的效率和保存分页信息所用的代价之后,决定了使用页目录和页 表2层转换。而使用2层转换最公平的方式就是页目录中的项数和页表中的项数都一样。由于所要保存足够的信息,又由于是32bit cpu 所以,一个PTE或者一个PDE的大小是4个字节也是有理由的。当这些确定了之后,也就确定了一页的大小。

    设一页大小是 x ,单位是字节。那么这样一页中有 (x/4) 个PTE或者PDE。一个PTE可以对应一页的地址空间,也就是大小为x个字节的地址空间,一个 Page Table 页中有(x/4) 个PTE,所以一个 Page Table 页可以对应(x/4)*x个字节的地址空间。一个PDE可以找到一个 Page Table 页,也就是大小为(x/4)*x个字节的地址空间,一个 Page Directory 页中有 (x/4) 个PDE,所以一个 Page Directory 页可以对应 (x/4)(x/4)*x 个字节的地址空间。现在需要用一个PDE页对应整个地址空间,整个地址空间是4G字节,也就是4*1024*1024*1024 个字节。所以 (x/4)(x/4)*x=4*1024*1024*1024 可以算出 x = 4*1024 字节,也就是 4k 字节。

地址转换的性能

    一旦使用了分页(CPU的相关寄存器的分页标志位被设置),所有的内存操作都使用的是虚拟地址,CPU会自动转换成物理地址,可以想象将会有非常大量的地 址转换,一次转换可能需要读页目录表,读页表,最后才在页中读写数据。所以有理由把一些页目录项和页表项放入高速缓存中来提高地址转换的速度。实际中也是 这样做的,对于 x86 cpu ,如果启用了分页,cpu 会使用一个叫做 TLB(Translation Look-Aside Buffer) 的高速缓存来存储经常被用到的页目录和页表项。

页目录的地址为什么是C0300000,1个页目录加上1024个页表为什么只使用了1024*4K的地址空间

    对于要映射整个4G地址空间,是需要1024个页表和1个页目录的,每个都是4KB大小,也就是 1024*4KB+1*4KB=4MB+4KB。而实际中Win2k把每个进程的页目录和页表映射到了从 0xC0000000到0xC03FFFFF 这4MB的地址空间中(页目录在0xC0300000开始的4K)。注意是4MB地址空间而不是4MB+4KB。1024个页表和1个页目录,应该是需要 (1024+1)*4KB的地址空间的。而现在Win2k只使用了1024*4KB的地址空间这是为什么?

    原因就是页表被映射到了进程的地址空间。
    如果页表和页目录没有被映射到进程的地址空间中,而一个进程的4GB地址空间又都映射了物理内存的话,那么就确实需要1024个物理页来存放页表,和另外1个物理页来存放页目录,也就是需要(1024+1)*4KB的物理内存。
但是页表被映射到了进程的地址空间中,这导致了一个页表的内容和页目录的内容是完全一样的,正是这种完全相同,使得将1024个页表加1个页目录映射到地址空间只需要1024*4KB的地址空间,其中的一个页表和页目录完全重合了。
    一个页表1024项,每项对应4KB地址空间,一个页表对应4MB的地址空间。1024个对应了整个4GB地址空间。1024个页表也被映射到了从 0xC0000000到0xC03FFFFF 的4MB地址空间中。这4MB地址空间也是由一个页表来对应的。我们来看对应于从 0xC0000000到0xC03FFFFF 这4MB的地址空间的页表。该页表有1024项,每项对应一页的地址空间,表明是否在物理内存中,如果在,物理地址是多少。而这个页表是对应页表所在的 4MB地址空间的,所以它的每一项对应的一页,正是每个页表所在的页。也就是说这个页表的每一项指出了一个页表是否有物理内存映射,如果有的话,物理地址 是多少。这正是页目录所做的工作。把1024个页表映射到了地址空间,导致了1024个页表中的一个的内容和页目录完全重合,它既是页目录又是页表。所以 1个页目录加上1024个页表只使用了1024*4K的地址空间。

    页表被映射到地址空间的什么地方,是由操作系统的设计者决定的,他会综合考虑各种问题,作出最后的决定。不过一旦页表所在的地址空间的地址决定了,那么页目录的地址也就决定了,除非他打算多使用一页的地址空间保存和现在一个页表中完全相同的内容。

    Win2k中把页表映射到了从 0xC0000000到0xC03FFFFF 的4MB地址空间中,我们来计算一下负责这4M地址空间的那个页表的地址,那个页表就是和页目录重合的页表。4MB地址空间的首地址0xC0000000 显然是由该页表的第一项负责的,我们用这个地址来计算。PTE_Address=(VirtualAddress>> 12)*4+0xC0000000,
(0xC0000000>>12)*4+0xC0000000=0xC0000*4+0xC0000000=0x300000+0xC0000000=0xC0300000
正是页目录的虚拟地址。

    0xC0300000到0xC0300FFF这4KB的地址空间,作为普通一页的话由一个PTE指明所在物理页的物理地址,作为一个页表所在页的话由一个PDE指明所在物理页的物理地址,作为页目录的话由CR3指明所在物理页的物理地址。
    0xC0300000到0xC0300FFF这4KB作为普通的一页是由哪个PTE对应呢,PTE_Address=(VirtualAddress& gt;>12)*4+0xC0000000,计算得到0xC0300C00。也就是说0xC0300C00处的4个字节作为PTE,指明了 0xC0300000到0xC0300FFF这4KB所在的物理页的物理地址。
    0xC0300000到0xC0300FFF这4KB作为一个页表所在页是由哪个PDE对应呢,PDE_Address= (VirtualAddress>>22)*4+0xC0300000,计算得到0xC0300C00。也就是说0xC0300C00处的4 个字节作为PDE,指明了0xC0300000到0xC0300FFF这4KB所在的物理页的物理地址。
    0xC0300000到0xC0300FFF这4KB作为页目录的话,由 CR3 指明所在物理页的物理地址。所以 0xC0300C00 处的4个字节的值,把标志位清0的话,就等于 CR3 中的值。

下面这个特殊地址的转换过程,你就会发现页目录和一个页表确实是重合了,而且它既是页目录又是页表。
虚拟地址 C0300C00 转换成物理地址,以下输出来自 kd。

kd> r cr3
r cr3
cr3=069ca000
// CPU第一步根据cr3里的物理地址找到页目录所在物理页
// 取C0300000的最高10bit, 1100 0000 00 = 11 0000 0000 = 300 ,作为页目录项索引,由于每项长4字节
// 所以页目录项的物理地址为 300*4+069ca000=069cac00
kd> !dd 069cac00
!dd 069cac00
# 69cac00 069ca063 01e2b063 00000000 01670163
# 69cac10 01671163 01672163 01673163 01674163
# 69cac20 01675163 01676163 01657163 01658163
# 69cac30 01659163 0165a163 0165b163 0165c163
# 69cac40 0165d163 0165e163 0165f163 016c0163
# 69cac50 01681163 01682163 01683163 01684163
# 69cac60 01685163 01686163 01687163 01688163
# 69cac70 01689163 0168a163 0168b163 0168c163
// 结果该页目录项中的物理地址(页目录项的高20bit是物理页帧号,低12bit是标志)是069ca000
// 注意页表的物理地址等于页目录的物理地址,说明了页目录和页表是重合的。

// CPU第二步根据该目录项中的物理地址找到页表所在的物理页
// 取C0300000的最高10bit之后的10bit, 11 0000 0000 = 300 ,作为页表项索引,由于每项长4字节
// 所以页表项的物理地址为 300*4+069ca000=069cac00
kd> !dd 069cac00
!dd 069cac00
# 69cac00 069ca063 01e2b063 00000000 01670163
# 69cac10 01671163 01672163 01673163 01674163
# 69cac20 01675163 01676163 01657163 01658163
# 69cac30 01659163 0165a163 0165b163 0165c163
# 69cac40 0165d163 0165e163 0165f163 016c0163
# 69cac50 01681163 01682163 01683163 01684163
# 69cac60 01685163 01686163 01687163 01688163
# 69cac70 01689163 0168a163 0168b163 0168c163
// 结果该页表项中的物理地址(页目录项的高20bit是物理页帧号,低12bit是标志)是069ca000

// CPU第三步根据页表项中的物理地址找到物理页,用C0300000低12bit作为页内偏移,
// 相加得到物理地址 ,低12bit, 1100 0000 0000 =c00,c00+069ca000=069cac00
// 这样就得到了虚拟地址 C0300C00 对应的物理地址 069cac00
kd> !dd 069cac00
!dd 069cac00
# 69cac00 069ca063 01e2b063 00000000 01670163
# 69cac10 01671163 01672163 01673163 01674163
# 69cac20 01675163 01676163 01657163 01658163
# 69cac30 01659163 0165a163 0165b163 0165c163
# 69cac40 0165d163 0165e163 0165f163 016c0163
# 69cac50 01681163 01682163 01683163 01684163
# 69cac60 01685163 01686163 01687163 01688163
# 69cac70 01689163 0168a163 0168b163 0168c163
// 该处的DWORD值为 069ca063
// 前面看到 CR3 的值为 069ca000

一个进程的页目录和页表本身所需要的物理内存

    一个进程需要物理页来放页表和页目录,如果有1024个页表,那么不是需要1024*4K=4M 的物理内存吗?一个进程只是页表信息就需要4M 的物理内存吗?不过实际上,当页目录中的一项有效标志位(第0位,最低位)为0,那么该项对应的页表就不存在,就不需要占用一个物理页。在前面的页目录的 例子中我们已经看到了用户地址空间中有多少个无效项(系统地址空间中的东西,基本上大家都一样)。也就是说实际上为了保存一个进程的页表用不了多少物理内 存。
    这也就是为什么要使用2级的地址转换。如果只使用一级,只用页表,那么每个进程1024个页表就必须都放在物理内存中,即每个进程需要4M物理内存来放页 表,这个代价对目前来说是太大了。使用2级地址转换,多一个步骤,虽然转换速度会变慢一些,但是节省了物理内存,在速度与内存之间寻求了平衡。

页目录项的 Write 标志位
    从前面页目录的例子中,可以看到页目录的标志 bits1-1 Write ,总是为1。
表明页表所在的物理页总是可写的。这是因为页表和页目录是由系统维护的,系统需要向其中写入东西。

保护模式,Flat Model,线性地址,逻辑地址,ring0,ring3

以下内容只针对x86

    Win2k 运行在保护模式(Protected Mode )下,是否运行在保护模式下,取决于PE(Protection Enable)标志位 (CR0 的 bit 0 )。为0表示实模式(Real-Address Mode)(当机器加电启动和重启的时候,x86 CPU 处于实模式下),为1表示保护模式。观察Win2k的CR0的bit0,值为1,表明运行在保护模式下。

    对于x86体系结构来说,分段机制是必须被使用的(分页机制是可选的,分段和分页可以同时使用,Win2k使用了分页机制)。比如CPU执行代码总是参考 代码段。在保护模式下,段寄存器(CS,DS,SS,ES,FS,GS)中放着的是段选择符,用于在某个描述符表中寻找段描述符。

    保护模式下的分段机制,有多种使用模型,Win2k使用的是一种叫做 Flat Model (平坦模型)。就是通过把段基址设为0,段界限设为4G,这样每个段都是整个地址空间,这样就隐藏了分段机制。

全局描述符表
全 局描述符表(GDT,global descriptor table)用来存放描述符,整个系统只有一个。由GDTR(全局描述符表寄存器)指出所在位置和大小。由于GDTR中的界限部分为16位,所以全局描述 符表最大可以为64KB,每个描述符占8个字节,所以全局描述符表中最多可以放8192个描述符。

段选择符(CS,DS,SS,ES,FS,GS中放的是段选择符)的格式定义如下(来自Intel手册):
段选择符,长2个字节,16bit。

Index: bit3-bit15 13位 在全局描述符表或者局部描述符表中的索引,可以索引8192个描述符
TI flag: bit2 1位 TI,table indicator,指定描述符表。为0在全局描述符表(GDT)中选择,为1在 当前的局部描述符表(LDT)中选择
RPL: bit0-bit1 2位 选择符的特权级

全局描述符表寄存器(GDTR,48bit)格式定义如下(来自Intel手册):

Table Limit: bit0-bit15 16位 指定描述符表的字节数。
Base Address: bit16-bit47 32位 指定描述符表的基地址。是线性地址。

段描述符格式定义如下:

typedef struct _SEG_DESCRIPTOR //size 8 bytes
{
unsigned short limit_0_15;
unsigned short base_0_15;
unsigned char base_16_23;

unsigned char accessed : 1;
unsigned char r_w_e : 1;
unsigned char e_c : 1;
unsigned char code_data : 1;
unsigned char app_system : 1;
unsigned char dpl : 2;
unsigned char present : 1;

unsigned char limit_16_19 : 4;
unsigned char unused : 1;
unsigned char always_0 : 1;
unsigned char seg_16_32 : 1;
unsigned char granularity : 1;

unsigned char base_24_31;
} SEG_DESCRIPTOR ,*PSEG_DESCRIPTOR;

limit_0_15,limit_16_19,granularity
段界限,两部分,共20bit。
如果granularity位为0,段界限的值以字节为单位。段最大为1MB。
如果granularity位为1,段界限的值以4KB为单位。段最大为4GB。

base_0_15,base_16_23,base_24_31
段基址,三部分,共32bit。

accessed,readable,conforming,code_data
accessed表示是否已经被访问过了。
code_data为0表示代码段,为1表示数据段。
对于数据段,r_w_e位表示是否可写,为0只读,为1可写。e_c位表示增长方向,为1向下增长。
对于代码段,r_w_e位表示是否可读,为0只执行,为1可读。e_c位表示conforming或者nonconforming。

app_system
0 = system, 1 = code or data。为1时,表明是代码段或者数据段。为0时表明是系统段,系统段一些位的含义和数据段或者代码段不同。有以下几种系统段:16-Bit TSS (Available),LDT,16-Bit TSS (Busy),16-Bit Call Gate,Task Gate,16-Bit Interrupt Gate,16-Bit Trap Gate,32-Bit TSS (Available),32-Bit TSS (Busy),32-Bit Call Gate,32-Bit Interrupt Gate,32-Bit Trap Gate。更多内容可以参考 Intel 手册。

dpl
指定段的特权级。

present
段是否在内存中

seg_16_32
段是16位还是32位。


下面看Win2k中实际的用法

一个ring3程序的段寄存器
(使用VC调试器获得,也可以自己写程序获得,也可以用SoftICE断到一个ring3程序中获得...)
CS = 001B DS = 0023 ES = 0023 SS = 0023 FS = 0038 GS = 0000

一个ring0程序的段寄存器
(使用KD获得,也可以写驱动程序获得,也可以用SoftICE断到一个ring0程序中获得...)
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000

GDTR的内容可以由指令sgdt得到(sgdt不是特权指令,ring3也可以执行)。
下面的内容来自SoftICE:
:gdt
Sel. Type Base Limit DPL Attributes
GDTbase=80036000 Limit=03FF
// GDTbase=80036000 Limit=03FF ,可以使用 sgdt指令做验证
// 16bit的界限值为03FF,表明Win2k中GDT只有1K,可以存放128个描述符

0008 Code32 00000000 FFFFFFFF 0 P RE
0010 Data32 00000000 FFFFFFFF 0 P RW
001B Code32 00000000 FFFFFFFF 3 P RE
0023 Data32 00000000 FFFFFFFF 3 P RW
0028 TSS32 801F4000 000020AB 0 P B
0030 Data32 FFDFF000 00001FFF 0 P RW
003B Data32 00000000 00000FFF 3 P RW
0043 Data16 00000400 0000FFFF 3 P RW
0048 Reserved 00000000 00000000 0 NP
0050 TSS32 80470040 00000068 0 P
0058 TSS32 804700A8 00000068 0 P
0060 Data16 00022AB0 0000FFFF 0 P RW
0068 Data16 000B8000 00003FFF 0 P RW
0070 Data16 FFFF7000 000003FF 0 P RW
0078 Code16 80400000 0000FFFF 0 P RE
0080 Data16 80400000 0000FFFF 0 P RW
0088 Data16 00000000 00000000 0 P RW
0090 Reserved 00000000 00000000 0 NP
0098 Reserved 00000000 00000000 0 NP
00A0 TSS32 8141A348 00000068 0 P
00A8 Reserved 00000000 00000000 0 NP
00B0 Reserved 00000000 00000000 0 NP
00B8 Reserved 00000000 00000000 0 NP
00C0 Reserved 00000000 00000000 0 NP
00C8 Reserved 00000000 00000000 0 NP
00D0 Reserved 00000000 00000000 0 NP
00D8 Reserved 00000000 00000000 0 NP
00E0 Code16 F0450000 0000FFFF 0 P RE ED
00E8 Data16 00000000 0000FFFF 0 P RW
00F0 Code16 8042DCE8 000003B7 0 P EO
00F8 Data16 00000000 0000FFFF 0 P RW
0100 Data32 F0460000 0000FFFF 0 P RW
0108 Data32 F0460000 0000FFFF 0 P RW
0110 Data32 F0460000 0000FFFF 0 P RW
0118 Reserved 00008003 00006120 0 NP
0120 Reserved 00008003 00006128 0 NP
0128 Reserved 00008003 00006130 0 NP
0130 Reserved 00008003 00006138 0 NP
0138 Reserved 00008003 00006140 0 NP
0140 Reserved 00008003 00006148 0 NP
0148 Reserved 00008003 00006150 0 NP
0150 Reserved 00008003 00006158 0 NP
0158 Reserved 00008003 00006160 0 NP
0160 Reserved 00008003 00006168 0 NP
0168 Reserved 00008003 00006170 0 NP
0170 Reserved 00008003 00006178 0 NP
0178 Reserved 00008003 00006180 0 NP
0180 Reserved 00008003 00006188 0 NP
0188 Reserved 00008003 00006190 0 NP
0190 Reserved 00008003 00006198 0 NP
0198 Reserved 00008003 000061A0 0 NP
01A0 Reserved 00008003 000061A8 0 NP
01A8 Reserved 00008003 000061B0 0 NP
01B0 Reserved 00008003 000061B8 0 NP
01B8 Reserved 00008003 000061C0 0 NP
01C0 Reserved 00008003 000061C8 0 NP
01C8 Reserved 00008003 000061D0 0 NP
01D0 Reserved 00008003 000061D8 0 NP
01D8 Reserved 00008003 000061E0 0 NP
01E0 Reserved 00008003 000061E8 0 NP
01E8 Reserved 00008003 000061F0 0 NP
01F0 Reserved 00008003 000061F8 0 NP
01F8 Reserved 00008003 00006200 0 NP
0200 Reserved 00008003 00006208 0 NP
0208 Reserved 00008003 00006210 0 NP
0210 Reserved 00008003 00006218 0 NP
0218 Reserved 00008003 00006220 0 NP
0220 Reserved 00008003 00006228 0 NP
0228 Reserved 00008003 00006230 0 NP
0230 Reserved 00008003 00006238 0 NP
0238 Reserved 00008003 00006240 0 NP
0240 Reserved 00008003 00006248 0 NP
0248 Reserved 00008003 00006250 0 NP
0250 Reserved 00008003 00006258 0 NP
0258 Reserved 00008003 00006260 0 NP
0260 Reserved 00008003 00006268 0 NP
0268 Reserved 00008003 00006270 0 NP
0270 Reserved 00008003 00006278 0 NP
0278 Reserved 00008003 00006280 0 NP
0280 Reserved 00008003 00006288 0 NP
0288 Reserved 00008003 00006290 0 NP
0290 Reserved 00008003 00006298 0 NP
0298 Reserved 00008003 000062A0 0 NP
02A0 Reserved 00008003 000062A8 0 NP
02A8 Reserved 00008003 000062B0 0 NP
02B0 Reserved 00008003 000062B8 0 NP
02B8 Reserved 00008003 000062C0 0 NP
02C0 Reserved 00008003 000062C8 0 NP
02C8 Reserved 00008003 000062D0 0 NP
02D0 Reserved 00008003 000062D8 0 NP
02D8 Reserved 00008003 000062E0 0 NP
02E0 Reserved 00008003 000062E8 0 NP
02E8 Reserved 00008003 000062F0 0 NP
02F0 Reserved 00008003 000062F8 0 NP
02F8 Reserved 00008003 00006300 0 NP
0300 Reserved 00008003 00006308 0 NP
0308 Reserved 00008003 00006310 0 NP
0310 Reserved 00008003 00006318 0 NP
0318 Reserved 00008003 00006320 0 NP
0320 Reserved 00008003 00006328 0 NP
0328 Reserved 00008003 00006330 0 NP
0330 Reserved 00008003 00006338 0 NP
0338 Reserved 00008003 00006340 0 NP
0340 Reserved 00008003 00006348 0 NP
0348 Reserved 00008003 00006350 0 NP
0350 Reserved 00008003 00006358 0 NP
0358 Reserved 00008003 00006360 0 NP
0360 Reserved 00008003 00006368 0 NP
0368 Reserved 00008003 00006370 0 NP
0370 Reserved 00008003 00006378 0 NP
0378 Reserved 00008003 00006380 0 NP
0380 Reserved 00008003 00006388 0 NP
0388 Reserved 00008003 00006390 0 NP
0390 Reserved 00008003 00006398 0 NP
0398 Reserved 00008003 000063A0 0 NP
03A0 Reserved 00008003 000063A8 0 NP
03A8 Reserved 00008003 000063B0 0 NP
03B0 Reserved 00008003 000063B8 0 NP
03B8 Reserved 00008003 000063C0 0 NP
03C0 Reserved 00008003 000063C8 0 NP
03C8 Reserved 00008003 000063D0 0 NP
03D0 Reserved 00008003 000063D8 0 NP
03D8 Reserved 00008003 000063E0 0 NP
03E0 Reserved 00008003 000063E8 0 NP
03E8 Reserved 00008003 000063F0 0 NP
03F0 Reserved 00008003 000063F8 0 NP
03F8 Reserved 00000000 00000000 0 NP

:dd 80036000 l 400
0010:80036000 00000000 00000000 0000FFFF 00CF9B00 ................
0010:80036010 0000FFFF 00CF9300 0000FFFF 00CFFB00 ................
0010:80036020 0000FFFF 00CFF300 400020AB 80008B1F ......... .@....
0010:80036030 F0000001 FFC093DF 00000FFF 0040F300 ..............@.
0010:80036040 0400FFFF 0000F200 00000000 00000000 ................
0010:80036050 00400068 80008947 00A80068 80008947 [email protected]...
0010:80036060 2AB0FFFF 00009302 80003FFF 0000920B ...*.....?......
0010:80036070 700003FF FF0092FF 0000FFFF 80009A40 ...p........@...
0010:80036080 0000FFFF 80009240 00000000 00009200 ....@...........
0010:80036090 00000000 00000000 00000000 00000000 ................
0010:800360A0 A3480068 81008941 00000000 00000000 h.H.A...........
0010:800360B0 00000000 00000000 00000000 00000000 ................
0010:800360C0 00000000 00000000 00000000 00000000 ................
0010:800360D0 00000000 00000000 00000000 00000000 ................
0010:800360E0 0000FFFF F0009F45 0000FFFF 00009200 ....E...........
0010:800360F0 DCE803B7 80009842 0000FFFF 00009200 ....B...........
0010:80036100 0000FFFF F0409346 0000FFFF F0409346 [email protected].@.
0010:80036110 0000FFFF F0409346 80036120 00000000 ....F.@. a......
0010:80036120 80036128 00000000 80036130 00000000 (a......0a......
0010:80036130 80036138 00000000 80036140 00000000 8a......@a......
0010:80036140 80036148 00000000 80036150 00000000 Ha......Pa......
0010:80036150 80036158 00000000 80036160 00000000 Xa......`a......
0010:80036160 80036168 00000000 80036170 00000000 ha......pa......
0010:80036170 80036178 00000000 80036180 00000000 xa.......a......
0010:80036180 80036188 00000000 80036190 00000000 .a.......a......
0010:80036190 80036198 00000000 800361A0 00000000 .a.......a......
0010:800361A0 800361A8 00000000 800361B0 00000000 .a.......a......
0010:800361B0 800361B8 00000000 800361C0 00000000 .a.......a......
0010:800361C0 800361C8 00000000 800361D0 00000000 .a.......a......
0010:800361D0 800361D8 00000000 800361E0 00000000 .a.......a......
0010:800361E0 800361E8 00000000 800361F0 00000000 .a.......a......
0010:800361F0 800361F8 00000000 80036200 00000000 .a.......b......
0010:80036200 80036208 00000000 80036210 00000000 .b.......b......
0010:80036210 80036218 00000000 80036220 00000000 .b...... b......
0010:80036220 80036228 00000000 80036230 00000000 (b......0b......
0010:80036230 80036238 00000000 80036240 00000000 8b......@b......
0010:80036240 80036248 00000000 80036250 00000000 Hb......Pb......
0010:80036250 80036258 00000000 80036260 00000000 Xb......`b......
0010:80036260 80036268 00000000 80036270 00000000 hb......pb......
0010:80036270 80036278 00000000 80036280 00000000 xb.......b......
0010:80036280 80036288 00000000 80036290 00000000 .b.......b......
0010:80036290 80036298 00000000 800362A0 00000000 .b.......b......
0010:800362A0 800362A8 00000000 800362B0 00000000 .b.......b......
0010:800362B0 800362B8 00000000 800362C0 00000000 .b.......b......
0010:800362C0 800362C8 00000000 800362D0 00000000 .b.......b......
0010:800362D0 800362D8 00000000 800362E0 00000000 .b.......b......
0010:800362E0 800362E8 00000000 800362F0 00000000 .b.......b......
0010:800362F0 800362F8 00000000 80036300 00000000 .b.......c......
0010:80036300 80036308 00000000 80036310 00000000 .c.......c......
0010:80036310 80036318 00000000 80036320 00000000 .c...... c......
0010:80036320 80036328 00000000 80036330 00000000 (c......0c......
0010:80036330 80036338 00000000 80036340 00000000 8c......@c......
0010:80036340 80036348 00000000 80036350 00000000 Hc......Pc......
0010:80036350 80036358 00000000 80036360 00000000 Xc......`c......
0010:80036360 80036368 00000000 80036370 00000000 hc......pc......
0010:80036370 80036378 00000000 80036380 00000000 xc.......c......
0010:80036380 80036388 00000000 80036390 00000000 .c.......c......
0010:80036390 80036398 00000000 800363A0 00000000 .c.......c......
0010:800363A0 800363A8 00000000 800363B0 00000000 .c.......c......
0010:800363B0 800363B8 00000000 800363C0 00000000 .c.......c......
0010:800363C0 800363C8 00000000 800363D0 00000000 .c.......c......
0010:800363D0 800363D8 00000000 800363E0 00000000 .c.......c......
0010:800363E0 800363E8 00000000 800363F0 00000000 .c.......c......
0010:800363F0 800363F8 00000000 00000000 00000000 .c..............

我们来分析一下:

对于ring3,CS=001B DS=0023 ES=0023 SS=0023 FS=0038 GS=0000,
DS,ES,SS,指向同一个段。
001B=0000000000011 0 11
0023=0000000000100 0 11
所以根据前面段选择符的定义,表示 CS,DS,ES,SS 都是在全局描述符表中进行选择。
选择符的特权级都是3(ring3)。对于CS,索引为3,由于每个描述符为8个字节,描述符相对于GDT开始处的地址为0x3*0x8=0x18。对于,DS,ES,SS,索引为4,描述符相对于GDT开始处的地址为0x4*0x8=0x20。

根据前面段描述符的定义,分析 80036018 开始的8个字节,和 80036020 开始的8个字节。
0010:80036010 0000FFFF 00CF9300 0000FFFF 00CFFB00 ................
0010:80036020 0000FFFF 00CFF300 400020AB 80008B1F ......... .@....
可以得出
Sel. Type Base Limit DPL Attributes
001B Code32 00000000 FFFFFFFF 3 P RE
0023 Data32 00000000 FFFFFFFF 3 P RW
可以看到,CS 对应的全局描述符表中的段描述符,是一个代码段,段基址为0,段界限为4G,DPL为3(ring3)。DS,ES,SS 对应的全局描述符表中的段描述符,是一个数据段,段基址为0,段界限为4G,DPL为3(ring3)。

对于ring0, cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000,
0008=0000000000001 0 00
0010=0000000000010 0 00
0023=0000000000100 0 11
Sel. Type Base Limit DPL Attributes
0008 Code32 00000000 FFFFFFFF 0 P RE
0010 Data32 00000000 FFFFFFFF 0 P RW
0023 Data32 00000000 FFFFFFFF 3 P RW
可以看到,代码段和堆栈段的DPL为0(ring0)。三个描述符的段基址都为0,段界限都为4G。

CS,DS,ES,SS,这些段都完全重叠了,而且都是当前的4G地址空间。和段的另外一种使用方法(不同的段在不同的一块地址空间)相比,现在的使用方法,整个地址空间是连续的,平坦的,所以叫做平坦模式(Flat Model)。

关于段寄存器(CS,DS,SS,ES,FS,GS),不可能每次参考一个段的时候CPU都去从内存中取出段描述符然后再做相应的处理,每个段寄存器还有看不到的部分,他们中存储着相应的段描述符中的信息。

全局描述表中的第一项不被使用,设为了"null descriptor" 。
0010:80036000 00000000 00000000
用来初始化没有被使用的段寄存器,以防止如果被不小心使用一个没有被使用的段寄存器,对系统造成不良影响。Win2k中,段寄存器GS就没有被使用,值都设为了0。

前面分析了 CS,DS,ES,SS 。对于 GS 来说,我们可以看到它的值总是为0,Win2k 并没有使用它。而对于 FS 来说,对于使用平坦模式的 Win2k 来说,它是一个例外,在其他地方会对 FS 做更多的介绍。

在 ntddk.h 中的以下内容,也说明了上面的一些分析。
#define KGDT_NULL 0
#define KGDT_R0_CODE 8
#define KGDT_R0_DATA 16
#define KGDT_R3_CODE 24
#define KGDT_R3_DATA 32
#define KGDT_TSS 40
#define KGDT_R0_PCR 48
#define KGDT_R3_TEB 56
#define KGDT_VDM_TILE 64
#define KGDT_LDT 72
#define KGDT_DF_TSS 80
#define KGDT_NMI_TSS 88

线 性地址(linear address),把32bit可寻址的4G地址空间看做连续的线性地址空间,线性地址空间中的地址叫线性地址。逻辑地址(logical address),逻辑地址由一个段选择符(16位)和一个段内偏移(32位)组成。也经常被叫做远程指针(far pointer)。x86 CPU 总是使用分段机制的(即使是使用了最少的分段机制的平坦模型),因此 x86 CPU 指令中的地址也总是逻辑地址,是相对于某一个段而言的地址。在保护模式下,x86 CPU 首先把逻辑地址转换成线性地址,然后再把线性地址转换成物理地址。

对于Win2k来说,由于使用了平坦模型,虚拟地址XXXXXXXX 和线性地址XXXXXXXX 指的是同一个地方。而平坦模型下,CS,DS,SS 这几个段的段基址为0,段界限为4G,就是整个地址空间,所以逻辑地址中的段内偏移的值就等于该逻辑地址转换成线性地址以后的值。

保护模 式下的 x86 CPU 有4个特权级,从0到3。被叫做ring0,ring1,ring2,ring3。ring0权限最大,ring3权限最小。对于Win2k来说,只使用 了ring0,ring3两个特权级。用户应用程序运行在ring3,系统内核运行在ring0。
    Win2k中进程的地址空间,被分为用户地址空间和系统地址空间。用户模式下的程序将不能访问系统地址空间,这就是通过保护机制实现的。页目录项和页表项 的 bit2 ,Owner标志位表明了访问所需的特权级,为0表示访问需要ring0的特权级,为1表示ring3的特权级就可以访问。在发生内存访问时,CPU会把 虚拟地址转换成物理地址。转换过程中,在从页目录项和页表项中获得物理地址的同时,会检查页目录项和页表项中的Owner标志位和当前的特权级,如果没有 足够的特权级将会产生一个 page-fault 异常。注意权限的检测和地址的转换是同时由硬件进行的,不会为此损失额外的性能。当前特权级(CPL,Current privilege level),当前执行程序的特权级,由CS,SS段寄存器中的最低2位指明。

保护模式下的 x86 CPU 提供了很多的保护机制,这也就是为什么叫保护模式,更多内容可以参考 Intel手册。

未来

    呃,从某种意义上来说,我认为未来是可以预知的。就像天气预报所作的,在今天就知道明天或者后天将要发生的事情。当然,实际上我认为对于人类来说未来是不 可预知的,人类所能知道的事情太有限了。呃,如果要估计我们现在讨论的分页机制还能在内存中活几年,就得估计CPU的发展,可能的新的需求的出现,人们的 创造力。挺费事,又没有预测以后一些人痛斥学校的愚昧的情景那么过瘾,所以我要说的未来不是关于分页的。我认为不久的将来人工智能和机器人将非常重要。当 然,实际上我认为当有真正的人工智能出现的时候,人类很有可能也就完了。


 

 

小议Windows NT/2000分页机制
WebCrazy([email protected])

内 存管理是操作系统最重要的一部分,其决定了操作系统的性能。Intel X86采用分段、分页的内存机制,Windows NT/2000充分利用了此项先进的机制。段内IA-32体系使用页目录(Page Directory)与页表(Page Table,SoftICE中Page命令可以显示出页目录与页表等)形成对4G地址的寻址能力。文中未特别说明,均讨论运行平台为Intel 32位处理器的Windows NT/2000,所提及的Windows也仅指Windows NT/2000。Windows中不管用户态与核心态的代码段、数据段与堆栈段基址均为0, 文中提到的逻辑地址(由段基址与偏移量两部分组成)与线性地址 值是相等的。由于对于用户来说线性地址是其可见的,若我未特别指出物理地址,所说的地址也仅指线性地址。

页目录(PDE)由1024 项组成,每项均指向一页表(PTE),每一页表也由1024个页组成,IA-32体系每页大小为4K,所以可寻址范围为 4G(1024*1024*4K)。Windows中每个进程都拥有其各自的进程地址空间,即拥有其各自的页目录与页表。每个进程均使用线性地址 C0300000H指向其特定的页目录所在的地址 ,而页目录中每项(即页表)均依次排列在线性地址C0000000H处,每个页表均占用 4K(1024*4)字节,如第一个页表位于C0000000H处,而第二个页表位于C0000000+1000H(4K),即C0001000中,依次 类推,计算公式即为C0000000H+页目录偏移值(线性地址的高10位)*1000H,在下面我将利用此公式。当然以上描述的前提是每个页表均位于物 理内存中(由页目录中每项中的P位指定),这也是为什么IA-32使用两级页表的原因,否则每个进程除其代码与数据等外还额外需要 4M(4*1024*1024)的存储器。

上面的机制即实现了物理地址寻址,也就实现了在Windows NT/2000中物理地址与线性地址的相互转换(虽然CPU在对内存操作时只需要线性地址转换成物理地址,但我们在分析程序代码等仍需要物理地址转换成线性地址)。照例先看看SoftICE的分析吧:

// addr explorer命令后以下操作将只在进程explorer的私有进程空间进行
:addr explorer

// 显示explorer进程页目录所在物理地址,即进程切换至explorer后PDBR(CR3)中的值
:addr
CR3 LDT Base:Limit KPEB Addr PID Name
.
.
.
00C10000 FF9FC920 036C explorer
.
.
.

/*

线性地址的格式:0-11位对应1页(4096字节)的偏移量
12-21位对当前页表中1024项中寻址
22-31位对页目录进行寻址
高20位(12-31位)又称为桢
根据上面提及的公式,即可以得到物理地址高20位的值,再加上线性地址页表偏移(作为物理
地址的低12位),即实现了线性地址转化为物理地址,用公式表示为:

  @(C0000000h +  PDE*1000h+PTE*4)        &0fffff000h+PO
=@(C0000000h +  4*(PDE*400h+PTE))       &0fffff000h+PO
=@(C0000000h + (PDE>>10d+PTE)<<2d)   &0fffff000h+PO
=@(C0000000h + (LA>>12d)<<2d)             &0fffff000h+PO
=@(C0000000h + (LA&0xFFFFF000)>>10d) &0fffff000h+PO

上式中用PDE与PTE分别代表Page Directory与Page Table的偏移值,用LA代表给定的线性
地址,用PO代表LA的低12位,用h与d分别代表16/10进制,@后表示取后地址指针中的内容。
如此分析后,线性地址C0300000所对应的页目录为300h,页表为300h,偏移量为0
则 C0000000h+PD*1000h+PT*4+PO=C0000000+300h*1000h+300h*4+0
*/

:dd c0000000+300*1000+300*4 l 4
0010:C0300C00 00C10063 01A31063 00000000 0141F163 c...c.......c.A.
|
|_低12位(0-11)063为属性位、Intel保留位与系统(OS)使用位

// 显示C0300000的物理地址(00C10000)
:? dword(@(c0000000+300*1000+300*4))&fffff000+C0300000&00000fff
00C10000

//用SoftICE验证
:phys dword(@(c0000000+300*1000+300*4))&fffff000+C0300000&00000fff
C0300000

:page C0300000
Linear Physical Attributes
C0300000 00C10000 P D A S RW

其实上面最后一条命令就可以实现所有其它指令的功能,下面我列出实现的代码段:

// 线性地址->物理地址
// SoftICE中Page命令可以实现此功能
// 一个线性地址对应唯一的物理地址
// 此函数若返回0说明此线性地址未对应物理地址

ULONG LinearAddressToPhysicalAddress(ULONG lAddress)
{
unsigned int *pAddr;
unsigned int *PageDirectoryEntry=(unsigned int *)0xC0300000;
unsigned int *PageTableEntry=(unsigned int *)0xC0000000;

//判断页目录是否有效,第0位(P)为存在位,请参阅相关书籍
if((!(PageDirectoryEntry[lAddress>>22]&0xFFFFF000))
&&(!(PageDirectoryEntry[lAddress>>22]&0x00000001)))
return 0;

//@(C0000000h+(LA&0xFFFFF000)>>10d)&0fffff000h+PO 见上叙述
pAddr=(int *)((int)PageTableEntry+((lAddress&0xFFFFF000)>>10));
if((*pAddr)&1)
return ((*pAddr) &0xFFFFF000) |(lAddress&0x00000FFF);
return 0;
}

那 么又如何逆向实现物理地址转换成线性地址呢?虽然其间没有任何关系,但因为知道页目录与页表的具体位置,可使用直接在这个范围中搜索的方法。理论上这个范 围最大为1024*1024*4(4M),但由于很多页目录项当前均不存在于物理内存中,所以实际上搜索范围小得多。这也导致一个问题,有可能导致蓝屏 (内核态访问不存在的地址)。所以以下给出的代码我检查了页目录中每一项的P位。

// 物理地址->线性地址
// 相当于SoftICE中Phys命令
// 搜索所有有效的页表寻找指定物理地址
// 有可能多个线性地址同时指向同一个物理地址
// 此函数若未输出任何结果表明当前还没有线性地址映射至此物理地址中

void PhysicalAddressToLinearAddress(ULONG pAddress)
{
unsigned int *pAddr;
unsigned int *PageDirectoryEntry=(unsigned int *)0xC0300000;
unsigned int *PageTableEntry=(unsigned int *)0xC0000000;
int i,j;
DbgPrint("/n");
for(i=0;i<1024;i++)
if((PageDirectoryEntry[i]&0xFFFFF000)&&(PageDirectoryEntry[i]&0x00000001))
for(j=0;j<1024;j++){
pAddr=(int *)((int)PageTableEntry+i*4096+j*4);
if((*pAddr)&0x00000001)
if(((*pAddr)&0xFFFFF000)==(pAddress&0xFFFFF000))
DbgPrint("%08X/n",
((i*4*1024*1024+j*4*1024)&0xFFFFF000)|(pAddress&0x00000FFF));
}
}

上面两个程序段涉及到2G-4G范围(线性地址C0000000以上)的内存访问,普通用户态的程序无法实现。在Windows中请使用设备驱动程序以使其在核心态正确执行。

那 么Windows又是如何利用分页机制以高效、合理的利用好有限的物理内存呢?Jeffrey Richter的经典著作<>全面阐述了Windows的内存管理机制,相关原理请具体参阅此书!下面我列出同一程序(mspaint.exe)的两个 运行实例的线性地址与物理地址的对应关系,以说明Windows的内存分页机制。

// 下面是mspaint.exe装入内存后各段的地址(两个同时运行的mspaint.exe进程的映射地址一致)
:map32 mspaint
Owner Obj Name Obj# Address Size Type
mspaint .text 0001 001B:01001000 0003A500 CODE RO
mspaint .data 0002 0023:0103C000 00002670 IDATA RW
mspaint .rsrc 0003 0023:0103F000 000116C8 IDATA RO
-------------
|
|_逻辑地址

// mspaint.exe第一个运行实例的线性地址与物理地址的对应关系

Linear Address Range Physical Address Range Attributes
-------------------- ---------------------- ----------
00010000 - 00010FFF 03A8B000 - 03A8BFFF 047
00020000 - 00020FFF 03BCC000 - 03BCCFFF 047
0006D000 - 0006DFFF 018BC000 - 018BCFFF 047
. . .
. . .
. . .
//mspaint.exe第一个实例的.text段
01001000 - 01001FFF 00596000 - 00596FFF 005
01002000 - 01002FFF 03F97000 - 03F97FFF 005
01003000 - 01003FFF 03D58000 - 03D58FFF 005
. . .
. . .
. . .
//mspaint.exe第一个实例的.data段
0103C000 - 0103CFFF 0225F000 - 0225FFFF 047
0103D000 - 0103DFFF 03620000 - 03620FFF 047
0103E000 - 0103EFFF 03C1E000 - 03C1EFFF 047
. . .
. . .
. . .
//mspaint.exe第一个实例的.rsrc段
0103F000 - 0103FFFF 01652000 - 01652FFF 025
01040000 - 01040FFF 02653000 - 02653FFF 005
01041000 - 01041FFF 003D4000 - 003D4FFF 00

 

 

启用PAE后内存分页机制的一点小问题

 

2007-09-16 10:26:44|  分类: 技术烂文 |  标签:pae  分页机制   |字号 订阅

 

关于Windows 2000的内存分页机制,jiurl的文章已经说得很清楚了,推荐阅读一下(见文末“参考资料”)。jiurl的文中说页目录被映射到了0xC0300000开始处的4K地址空间,但是我在Windows XP SP2下测试时,发现了一点小问题,在SoftICE中输入dd c0300000命令:

 

发现该地址的内容全是问号,难道Windows XP中页目录被映射到了其它地址?来看看WinDbg给的答案,WinDbg中输入!pte命令:

 

果然,页目录跑到了0xC0600000。等等,细看发现WinDbg给出的地址是64位的,我装的是32位的系统呀,怎么会出现64位的地址捏?立马想到了PAE(我在《Intel® 64 and IA-32 Architectures Software Developer’s Manual》中看到PAE=Page Address Extension,页地址扩展;但是网上大部分文章还有WinDbg的帮助中PAE=Physical Address Extension,物理地址扩展,不清楚哪个是对的),查看系统盘根目录下的Boot.ini,发现又没有/pae启动选项。搜索了一下,最后在WinDbg的帮助中找到这样一段话,原文如下:

 

   On 32-bit operating systems, hardware-enforced DEP requires Physical Address Extension (PAE). Therefore, when DEP is enabled on a computer that supports hardware-enforced DEP, 32-bit versions of the Windows operating system automatically enable PAE and ignores /nopae.

意思大致是说当启用DEP后,32位Windows系统会自动启用PAE并且忽略/nopae选项。原来如此,我的Boot.ini里有/noexecute=optin选项,该选项会启用DEP。好,为了验证前面的想法,先把PAE给禁用了,编辑系统盘根目录下的Boot.ini文件,修改/noexecute=alwaysoff启动参数即可禁用DEP和PAE:

 

 [boot loader]

timeout=0

default=multi(0)disk(0)rdisk(0)partition(1)WINDOWS

[operating systems]

multi(0)disk(0)rdisk(0)partition(1)WINDOWS="Microsoft Windows XP Professional" /fastdetect /noexecute=alwaysoff

multi(0)disk(0)rdisk(0)partition(1)WINDOWS="Microsoft Windows XP Professional 调试" /fastdetect /noexecute=alwaysoff /debug /debugport=com1 /baudrate=115200

 

 

重启一下,再看看WinDbg的!pte命令输出:

 

呵呵,看到0xC0300000了,而且是32位的地址,dd c0300000也看到有内容了,说明了确实是PAE影响了页目录的映射地址,至于更深入的问题我就暂时无心思考了……

 

 

 

参考资料:

 

《JIURL玩玩Win2k内存篇 分页机制》

《深入解析Windows操作系统》

《Intel® 64 and IA-32 Architectures Software Developer’s Manual》(英文)

 

使用WinDBG分析启用PAE后的分页机制

2009-09-23 20:03:04|  分类: 默认分类 |字号 订阅

使用WinDBG分析启用PAE后的分页机制

上次通过windbg查看了windos XP内存分页的机制,但在PAE打开的机器上情况又有些不一样了。
PAE就是Physical Address Extension(物理内存扩展)。

如何打开PAE:
修改BOOT.INI,把选项/noexecute改为:/noexecute=optin。(如果/noexecute=alwaysoff则会关闭PAE)。
我的机器如下:
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect
控制寄存器CR4的第5位(CR4[5])用来启用PAE。

如何确认PAE已经打开:
在"我的电脑"上右键,选择"属性",如果常规选项卡的最下面有“物理地址扩展”,表示PAE已经打开.

打开PAE有什么用:
打开了PAE,IA-32 CPU的寻址能力就从原来的4GB扩展到64GB。

对于我们程序中的一个线性地址,cpu是如何把它转到到物理地址的?
一个32位的线性地址,启用PAE后,分为4部分:
PDIndex : 2位
PDEIndex: 9位
PTEIndex: 9位
OFFSET:   12位

CPU会首先通过CR3寄存器找到PD的基地址PDBase,通过PDIndex找到PDEBase:
PDEBase = PDBase[PDIndex];
然后通过PDEIndex找到PTE的地址:
PTEAddress = PDEBase[PDEIndex];
通过PTEAddress就可以找到某一个内存页的地址:
PAGEAddress = PTEAddress[PTEIndex];
要访问的物理地址就是 PAGEAddress+OFFSET;

还是来看看下面程序:
#include "stdafx.h"

char *hello = "ABCDEFG";
int main(int argc, char* argv[])
{
 printf("%x - %s\n", &hello, hello);
 getchar();
 return 0;
}

程序编译运行后显示:
422d14 - ABCDEFG
hello指针的地址是:0x422d14.

启动windbg,附加到该进程,输入命令:
0:001> dd 422d14
00422d14  0042001c c0000005 0000000b 00000000
00422d24  c000001d 00000004 00000000 c0000096
00422d34  00000004 00000000 c000008d 00000008
00422d44  00000000 c000008e 00000008 00000000
00422d54  c000008f 00000008 00000000 c0000090
00422d64  00000008 00000000 c0000091 00000008
00422d74  00000000 c0000092 00000008 00000000
00422d84  c0000093 00000008 00000000 00000003
字符串”ABCDEFG“的地址是:0x0042001c.
0:001> db 0042001c
0042001c  41 42 43 44 45 46 47 00-00 00 00 00 00 00 00 00  ABCDEFG.........
0042002c  5f 66 69 6c 62 75 66 2e-63 00 00 00 73 74 72 20  _filbuf.c...str
0042003c  21 3d 20 4e 55 4c 4c 00-5f 66 69 6c 65 2e 63 00  != NULL._file.c.
0042004c  70 72 69 6e 74 66 2e 63-00 00 00 00 66 6f 72 6d  printf.c....form
0042005c  61 74 20 21 3d 20 4e 55-4c 4c 00 00 69 33 38 36  at != NULL..i386
0042006c  5c 63 68 6b 65 73 70 2e-63 00 00 00 00 00 00 00  \chkesp.c.......
0042007c  54 68 65 20 76 61 6c 75-65 20 6f 66 20 45 53 50  The value of ESP
0042008c  20 77 61 73 20 6e 6f 74-20 70 72 6f 70 65 72 6c   was not properl

0:001>.formats 0042001c
Evaluate expression:
  Hex:     0042001c
  Decimal: 4325404
  Octal:   00020400034
  Binary:  00000000 01000010 00000000 00011100
  Chars:   .B..
  Time:    Fri Feb 20 09:30:04 1970
  Float:   low 6.06118e-039 high 0
  Double:  2.13703e-317


对于地址0x0042001c (00 000000010 000100000 000000011100),其
PDBaseIndex = 0;
PDEIndex     = 2;
PTEIndex     = 0x20;
OFFSET       = 0x1C;

用windbg启动一个本地的内核调试:
lkd> !process 0 0 testpte.exe
PROCESS 857df020  SessionId: 0  Cid: 0730    Peb: 7ffd5000  ParentCid: 06d0
    DirBase: 06fc0540  ObjectTable: e3728948  HandleCount:   7.
    Image: TestPTE.exe

我们可以看到cr3寄存器的地址为:06fc0540。


lkd> !dd 06fc0540
# 6fc0540 135a8801 00000000 31fa9801 00000000
# 6fc0550 1432a801 00000000 06ca7801 00000000
# 6fc0560 29438801 00000000 293f9801 00000000
# 6fc0570 292ba801 00000000 29437801 00000000
# 6fc0580 2d857801 00000000 2d9d8801 00000000
# 6fc0590 2d799801 00000000 2dc96801 00000000
# 6fc05a0 3d0dd801 00000000 38170801 00000000
# 6fc05b0 28fb5801 00000000 37b2c801 00000000

由于PDBaseIndex = 0;页目录基地址为:135a8000

lkd> !dd 135a8000
#135a8000 17fb7867 00000000 100c2867 00000000
#135a8010 0a176867 00000000 00000000 00000000
#135a8020 00000000 00000000 00000000 00000000
#135a8030 00000000 00000000 00000000 00000000
#135a8040 00000000 00000000 00000000 00000000
#135a8050 00000000 00000000 00000000 00000000
#135a8060 00000000 00000000 00000000 00000000
#135a8070 00000000 00000000 00000000 00000000

由于PDEIndex = 2;页表的基地址为:0a176000

lkd> !dd 0a176000+0x20*8
# a176100 23593025 80000000 00000000 00000000
# a176110 09adc886 00000000 08a4e886 00000000
# a176120 135df886 00000000 1034d884 00000000
# a176130 00000000 00000000 00000000 00000000
# a176140 00000000 00000000 00000000 00000000
# a176150 00000000 00000000 00000000 00000000
# a176160 00000000 00000000 00000000 00000000
# a176170 00000000 00000000 00000000 00000000


由于PTEIndex = 0x20;内存页的基地址为:23593000
加上0x1c的偏移,物理地址0x2359301c处的内容就是虚拟地址0x0042001c处的内容。

lkd> !db 2359301c
#2359301c 41 42 43 44 45 46 47 00-00 00 00 00 00 00 00 00 ABCDEFG.........
#2359302c 5f 66 69 6c 62 75 66 2e-63 00 00 00 73 74 72 20 _filbuf.c...str
#2359303c 21 3d 20 4e 55 4c 4c 00-5f 66 69 6c 65 2e 63 00 != NULL._file.c.
#2359304c 70 72 69 6e 74 66 2e 63-00 00 00 00 66 6f 72 6d printf.c....form
#2359305c 61 74 20 21 3d 20 4e 55-4c 4c 00 00 69 33 38 36 at != NULL..i386
#2359306c 5c 63 68 6b 65 73 70 2e-63 00 00 00 00 00 00 00 \chkesp.c.......
#2359307c 54 68 65 20 76 61 6c 75-65 20 6f 66 20 45 53 50 The value of ESP
#2359308c 20 77 61 73 20 6e 6f 74-20 70 72 6f 70 65 72 6c  was not properl

你可能感兴趣的:(Windows)