JIURL玩玩Win2k内存篇 分页机制.docx
- 文档编号:25459590
- 上传时间:2023-06-09
- 格式:DOCX
- 页数:52
- 大小:40.84KB
JIURL玩玩Win2k内存篇 分页机制.docx
《JIURL玩玩Win2k内存篇 分页机制.docx》由会员分享,可在线阅读,更多相关《JIURL玩玩Win2k内存篇 分页机制.docx(52页珍藏版)》请在冰豆网上搜索。
JIURL玩玩Win2k内存篇分页机制
基本概念
Windows2000使用基于分页机制的虚拟内存。
每个进程有4GB的虚拟地址空间。
基于分页机制,这4GB地址空间的一些部分被映射了物理内存,一些部分映射硬盘上的交换文件,一些部分什么也没有映射。
程序中使用的都是4GB地址空间中的虚拟地址。
而访问物理内存,需要使用物理地址。
下面我们看看什么是物理地址,什么是虚拟地址。
物理地址(physicaladdress):
放在寻址总线上的地址。
放在寻址总线上,如果是读,电路根据这个地址每位的值就将相应地址的物理内存中的数据放到数据总线中传输。
如果是写,电路根据这个地址每位的值就将相应地址的物理内存中放入数据总线上的内容。
物理内存是以字节(8位)为单位编址的。
虚拟地址(virtualaddress):
4G虚拟地址空间中的地址,程序中使用的都是虚拟地址。
如果CPU寄存器中的分页标志位被设置,那么执行内存操作的机器指令时,CPU会自动根据页目录和页表中的信息,把虚拟地址转换成物理地址,完成该指令。
比如moveax,004227b8h,这是把地址004227b8h处的值赋给寄存器的汇编代码,004227b8这个地址就是虚拟址。
CPU在执行这行代码时,发现寄存器中的分页标志位已经被设定,就自动完成虚拟地址到物理地址的转换,使用物理地址取出值,完成指令。
对于IntelCPU来说,分页标志位是寄存器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,pagedirectoryentry),页目录项中有这个虚拟地址所对应页表的物理地址。
有了页表的物理地址,根据虚拟地址的第12位到第21位这10位的值作为索引,找到该页表中相应的页表项(PTE,pagetableentry),页表项中就有这个虚拟地址所对应物理页的物理地址。
最后用虚拟地址的最低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,有着差不多的结构。
使用Win2kDDK所附带的内核调试器,KernelDebugger(KD),我们可以得到有效的页目录项和页表项的结构定义,对于使用X86CPU的系统,该结构定义如下
!
strctHARDWARE_PTE_X86
struct_HARDWARE_PTE_X86(sizeof=4)
+0bits0-0Valid
+0bits1-1Write
+0bits2-2Owner
+0bits3-3WriteThrough
+0bits4-4CacheDisable
+0bits5-5Accessed
+0bits6-6Dirty
+0bits7-7LargePage
+0bits8-8Global
+0bits9-9CopyOnWrite
+0bits10-10Prototype
+0bits11-11reserved
+0bits12-31PageFrameNumber
bits12-31PageFrameNumber:
页目录项或者页表项的第12到第31位,长20位。
物理页的页帧号。
(将这32位和0xFFFFF000做与运算,就得到了该4KB物理页第一个字节的地址)由于页的大小是4KB,所以只需要20位,就可以寻址4G大小范围内的每一页。
对于页目录项来说,所得的物理页中放着的是一个页表。
bits0-0Valid:
为0无效,该页没有映射物理内存。
为1有效。
该页映射了物理内存。
bits1-1Write:
为0该页只读。
为1该页可以读写。
bits2-2Owner:
为0访问该页需要ring0权限,只有核心态(kernel-mode)的代码才可以访问。
为1访问该页ring3权限就可以,用户态(user-mode)代码就可以访问。
bits3-3WriteThrough:
为0对相关页使用write-backcaching策略。
为1对相关页使用write-throughcaching策略。
直写式(Write-through),在CPU向Cache写入的同时,也把数据写入相应内存单元。
保证Cache和内存中相应单元数据的一致性。
直写式速度慢,而且有些操作是不必要的,比如CPU连续多次更新一个Cache单元的内容,将导致相应内存单元连续多次被写入,而效果其实和写入最后一次更新是一样的。
回写式(Write-back),CPU修改了Cache的内容后,并不立即修改内存中相应的单元。
只有当回写操作被执行的时候,才修改相应内存单元。
比如该Cache单元的内容从Cache中撤销时触发回写操作。
回写式速度快,也避免了一些不必要的操作。
如果CR0中的CD(cachedisable)标志为1,则处理器忽略WriteThrough标志。
CD标志,CR0寄存器的第30bit
。
观察发现,初始化之后的Win2k中,该位为0。
也就是说页目录项和页表项中的WriteThrough标志是起作用的。
bits4-4CacheDisable:
为0允许Cache该页。
为1禁止Cache该页。
如果CR0中的CD(cachedisable)标志为1,则处理器忽略CacheDisable标志。
CD标志,CR0寄存器的第30bit
。
观察发现,初始化之后的Win2k中,该位为0。
也就是说页目录项和页表项中的CacheDisable标志是起作用的。
bits5-5Accessed:
为0该页没有被访问(读出或者写入)过。
为1该页被访问(读出或者写入)过。
bits6-6Dirty:
为0该页中的内容没有被改动过。
为1该页中的内容已经被改动过了(被写过)。
bits7-7LargePage:
为0表示页大小为4K,为1表示页大小为4M。
bits8-8Global:
为0表示不是globalpage。
为1表示是一个globalpage。
如果CR4中的pageglobalenable(PGE)标志为1,表示允许pageglobal,那么当进程转换时在TLB(Translationlookasidebuffer)高速缓存中的globalpage不会失效。
用来防止常用页(比如内核或者操作系统的执行代码所在页)被换出TLB高速缓存。
寄存器CR4的PGE标志是第7位。
观察发现,初始化之后的Win2k中,该位为1。
bits9-9CopyOnWrite:
用于Copy-on-Write机制。
bits10-10Prototype:
用于进程间内存共享机制。
bits11-11reserved:
保留
页目录和页表
我们可以使用SoftICE获得指定进程的页目录,方法如下,首先不加参数的addr命令,将列出当前系统中的进程。
然后addr进程名,切换到该进程的地址空间。
然后ddc0300000l1000,将会在命令窗口输出0xc0300000处的0x1000字节(16进制,也就是4K字节)。
然后退出SoftICE,使用SymbolLoader的菜单中的File->SaveSoftICEHistoryAS..就可以把刚才输出的内容保存到文件中。
每个进程的页目录都映射到了0xc0300000处,所以我们就得到了页目录的内容。
我也写了一个叫JiurlPdPtSee的程序,可以输出指定进程的页目录和页表。
以下的内容就来自这个程序。
打开的一个记事本进程的页目录:
c0300000:
05f5b067058ae067067b506700eae067
c0300010:
03bfa067000000000000000000000000
c0300020:
00000000000000000000000000000000
c0300030:
00000000000000000000000000000000
c0300040:
00000000000000000000000000000000
c0300050:
00000000000000000000000000000000
c0300060:
00000000000000000000000000000000
c0300070:
00000000000000000000000000000000
c0300080:
00000000000000000000000000000000
c0300090:
00000000000000000000000000000000
c03000a0:
00000000000000000000000000000000
c03000b0:
00000000000000000000000000000000
c03000c0:
00000000000000000000000000000000
c03000d0:
00000000000000000000000000000000
c03000e0:
00000000000000000000000000000000
c03000f0:
00000000000000000000000000000000
c0300100:
043b1067000000000000000000000000
c0300110:
00000000000000000000000000000000
c0300120:
00000000000000000000000000000000
c0300130:
00000000000000000000000000000000
c0300140:
00000000000000000000000000000000
c0300150:
00000000000000000000000000000000
c0300160:
00000000000000000000000000000000
c0300170:
00000000000000000000000000000000
c0300180:
00000000000000000000000000000000
c0300190:
00000000000000000000000000000000
c03001a0:
00000000000000000000000000000000
c03001b0:
00000000000000000000000000000000
c03001c0:
00000000000000000000000000000000
c03001d0:
00000000000000000000000000000000
c03001e0:
00000000000000000000000000000000
c03001f0:
00000000000000000000000000000000
c0300200:
00000000000000000000000000000000
c0300210:
00000000000000000000000000000000
c0300220:
00000000000000000000000000000000
c0300230:
00000000000000000000000000000000
c0300240:
00000000000000000000000000000000
c0300250:
00000000000000000000000000000000
c0300260:
00000000000000000000000000000000
c0300270:
00000000000000000000000000000000
c0300280:
00000000000000000000000000000000
c0300290:
00000000000000000000000000000000
c03002a0:
00000000000000000000000000000000
c03002b0:
00000000000000000000000000000000
c03002c0:
00000000000000000000000000000000
c03002d0:
00000000000000000000000000000000
c03002e0:
00000000000000000000000000000000
c03002f0:
00000000000000000000000000000000
c0300300:
00000000000000000000000000000000
c0300310:
00000000000000000000000000000000
c0300320:
00000000000000000000000000000000
c0300330:
00000000000000000000000000000000
c0300340:
00000000000000000000000000000000
c0300350:
00000000000000000000000000000000
c0300360:
00000000000000000000000000000000
c0300370:
00000000000000000000000000000000
c0300380:
00000000000000000000000000000000
c0300390:
00000000000000000000000000000000
c03003a0:
00000000000000000000000000000000
c03003b0:
00000000000000000000000000000000
c03003c0:
00000000000000000000000000000000
c03003d0:
00000000000000000000000000000000
c03003e0:
00000000000000000000000000000000
c03003f0:
00000000000000000000000000000000
c0300400:
00000000000000000000000000000000
c0300410:
00000000000000000000000000000000
c0300420:
00000000000000000000000000000000
c0300430:
00000000000000000000000000000000
c0300440:
00000000000000000000000000000000
c0300450:
00000000000000000000000000000000
c0300460:
00000000000000000000000000000000
c0300470:
00000000000000000000000000000000
c0300480:
00000000000000000000000000000000
c0300490:
00000000000000000000000000000000
c03004a0:
00000000000000000000000000000000
c03004b0:
00000000000000000000000000000000
c03004c0:
00000000000000000000000000000000
c03004d0:
00000000000000000000000000000000
c03004e0:
00000000000000000000000000000000
c03004f0:
00000000000000000000000000000000
c0300500:
00000000000000000000000000000000
c0300510:
00000000000000000000000000000000
c0300520:
00000000000000000000000000000000
c0300530:
00000000000000000000000000000000
c0300540:
00000000000000000000000000000000
c0300550:
00000000000000000000000000000000
c0300560:
00000000000000000000000000000000
c0300570:
000000000000000000000000
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JIURL玩玩Win2k内存篇 分页机制 JIURL 玩玩 Win2k 内存 分页 机制