JIURL玩玩Win2k内存篇 分页机制 (二)

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

    当执行一条访问内存的指令时,如果寄存器中的分页标志位已经被设置,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

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值