Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html
无处不在的页异常
1. 无效PTE的情况
之前我们在保护模式中分析了PTE的情况,但是其是有效的,如果无效则其数据结构是不同的。
如果要区分是否有效,关键是看PTE中的P位,如果P位为1,则为有效,否则就为无效,无效分各种情况。
1)磁盘中存在许多个 pagefile.sys文件,该文件就是所谓的虚拟内存,当内存不足时其会存放在pagefile.sys文件中,并且将pte修改为(a),原来的物理页被别处使用,
当访问pte时,遇到这种情况,其会从[1-4]位中找到其所在的pagefile.sys位置,然后将其映射到磁盘上。
2)当进程需要一个零页面,其可以直接访问(b)这种PTE格式的内存,操作系统发现就会通过缺页异常为其分配一个零页面的,这很方面。
3)当该页面正在转移到磁盘上,或从磁盘转移到内存中,就会是(c)这样子,这个很好理解。
4)最后一种就是未知原因,如果遇到这种情况,就需要检查VAD树,看看该页是否在当前的进程中,再做下一步处理,如果能查找,则分配内存,如果不存在,则会报c000005错误。
注意:只有在三环才存在这种错误,因为在零环是没有Vad树的,这个很容易理解。
2. __MMPTE
__MMPTE是一个联合体,如下存在几种PTE种类,其有效和各种无效的。
kd> dt _MMPTE -r1
nt!_MMPTE
+0x000 u : __unnamed
+0x000 Long : Uint4B
+0x000 Hard : _MMPTE_HARDWARE
+0x000 Flush : _HARDWARE_PTE // 正常使用的PTE
+0x000 Proto : _MMPTE_PROTOTYPE // 原型PTE
+0x000 Soft : _MMPTE_SOFTWARE
+0x000 Trans : _MMPTE_TRANSITION
+0x000 Subsect : _MMPTE_SUBSECTION
+0x000 List : _MMPTE_LIST
1)原型PTE的用法
当进程第一次引用一个已被映射的内存区对象的视图中的页面中,内存管理器利用原型PTE中的信息来填充页表中实际的PTE。
原型PTE常用在共享内存中,比如映射文件,共享节区等,所谓原型PTE,其本质就是“状态的描述”,其会帮助修正物理指向。
其原型PTE如上图所示,进程A B共享一个物理页面,但该页面换入虚拟内存中,此时进程AB共同指向内存段对象的原型PTE:
① 当A第一次访问时,其触发页异常错误,将页面加载到内存并且A的PTE从段对象转而指向该物理页P2,并且将段对象中的原型PTE也指向P2;
② 此时B也访问页面P2,其指向原型PTE,当触发页异常时,页异常处理程序发现存在原型PTE,其会自动去解析原型PTE,发现其指向P2,此时其会将B进程的PTE直接指向P2。
如果你理解了这种,你会发现原型PTE就是所谓的“记录状态”,其为啥在共享中常用呢?因为其多个PTE共同指向原型PTE,这样可以提高效率。
如果不用原型PTE,则A进程修复完之后还要去B、C、···D共同将页面置换(注意,不同进程存在自己的页目录表基址,即存在自己独立的PTE),而共同指向一个原型PTE,其存储在MmPfnDataBase中。
如下图,其指向原型PTE的指针,其中“原型位”这个概念你一定要明确,现在再来看很好理解了。
2)写拷贝原理
PTE各种属性为中并没有写拷贝的概念,可写拷贝的页面,其PTE中的W位为0,此时如果强写会触发0E号页异常;
此时其会去从VAD中查看该页的属性,发现其是写拷贝属性,则重新复制一份,之后修改其PTE,这样就实现了写拷贝了。
3.MDL内存映射
1)内存中存在两种映射:
① MmIoSpace,其传入物理地址,其返回一个虚拟地址;
② Mdl,其传入一个虚拟地址,其再帮你映射一份。
使用Mdl就会一个物理地址存在两个虚拟地址,如果一个虚拟地址修改了,就直接更改物理地址了。
2)MDL用法:
① IoAllocateMdl 创建一个MDL,写入映射的地址和大小,其MDL是一个连续的链表数据结构;
② MmProAndLockPages NoChange置为1,防止需要映射的内存置换出,否则发生页面置换,映射时为空则会出现蓝屏;
③ MmMapLockedPages 将MDL在内存中再映射一份,在这里就实现映射,其返回一个内存地址,我们就可以直接对该内存地址进行读写;
④ MmUnmapLockedPages 解除映射,此时就原来的虚拟地址对应物理地址;
⑤ IoFreeMdl 将该mdl从mdl链表中释放出去。
其中注意在第③步时才会发生映射,即一个物理地址存在两份虚拟地址,MDL只是一个相关数据结构,驱动中可以常见,我们之后会来分析有关数据结构。
原文:https://www.cnblogs.com/onetrainee/p/12763011.html