windows下由于启用了页机制,所有软件层面的地址操作都是VA,通过descriptor(base address(32bit))+offset得到的线性地址并不直接对应物理地址,而是经过页转换机构再做一次转换得到物理地址,这样的转换是硬件提供的能力,转换过程被说的比较多了,大体是通过cr3寄存器得到page direcotry的物理地址,Vitrual Address的高10位就是一个(pde)page direcotry entry的index,或许可以像这样表示cr3[VA>>22],一个pde又指向了一个page table,VA接下来的10bit就是page table中的一个索引,即一条pte(page talbe entry),pte中存放了page的地址,低12位就是在前述转换过程中得到的page中的offset。

需要特别说明的是,pde and pte中存放的是物理帧号(physical frame number)位于pde or pte的高20bit,也就是说可以表示1M个物理帧,每个物理帧大小是4kb,这样就可以表示4GB的内存。

说了半天还没到自映射机制,前面说的都是硬件提供的能力,只要是拿到一个VA硬件层面都进行相同的转换步骤,windows要做内存管理,就需要维护page directory和 page tables,如何通过一个VA得到它所在的页的VA以及所在的页表的VA呢?

微软提供了下面几个宏处理给定的VA

#define MiGetPdeAddress(VA)  ((PMMPTE)(((((ULONG)(VA)) >> 22) << 2) + PDE_BASE))//此处PDE_BASE为0xc0300000(这也是一个VA,经页转换后得到的是PD的起始地址,下面就是所谓的自映射了,页转换机构利用VA的高十位(0x300)索引到一个PDE,这个PDE的特别之处是并没有指向一个page table而是指向了page directory的起始地址,一个PD占据一页,一个PT也占据一页),继续把page directory作为一个page table,再用VA的中间10位(还是0x300)又索引到了page directory的起始位置,低12位是0,即offset为0,最终得到的就是Page Directory的起始地址。那么VA先右移22,再左移2(相当于乘以4)加上PDE_BASE经过得到一个VA,经过两次自映射,加上offset后,得到的物理地址就是PDE的物理地址。

#define MiGetPteAddress(va) ((PMMPTE)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE))
这里的PTE_BASE是一个常量,为0xC0000000,也就是说page directory entry的索引(0x300)仍然索引到page directory的起始位置,和上面的宏一样,又是一次自映射。

#define MiGetVirtualAddressMappedByPte(PTE) ((PVOID)((ULONG)(PTE) << 10))//如果是给了一个VA,想要得到所在page的起始地址,只需将VA的低12位清零就可以得到VA所在页的VA,但这里给的是PTE(相当于(*PDE)),因为pte的高十位总是指向PD的起始位置,左移10位之后就相当于取消了这次自映射,当然这里的转换只对利用自映射的va有效。

再说一下,exe载入内存的时候,如何建立描述符,首先根据image的大小分配若干页的内存,这里假设image 在内存中占80kb,基址是0x00400000h,系统共分配20页的内存,起始页的VA假设是1110010000|1101110000|000000000000b(pde index(0x390):pte index(0x370):offset(0x0)),则descriptor.base+00400000h=E4370000h->descriptor.base=E3F70000h,那么code段描述符中的基址就可以根据其相对于00400000h的偏移加上E4370000h得到,比如code段的va是00401000h,那么他的描述符中的基址为E3F71000h,正好是从内存中image的第2页开始。更进一步,将新建code段描述符在GDT中的index(选择子)载入到cs,程序就可以运行了。

总起来说,硬件的转换机制并没有改变,只是windows利用硬件提供的这种能力使自己能方便的维护PD和PT

经过后来的相关资料的学习,PDE_BASE这个值是一个线性地址,微软通过一个宏来指定他的值,而CR3总的值一定是物理地址,并且在切换进程的时候这个值是会改变的

另外描述符实际上是对PE中的VA进行了一层包装

VA:vitual address

PTE:page table entry

PDE:page directory entry

PD:page directory

PT:page table

windows的页自映射机制的更多相关文章

  1. x86平台上的Windows页表映射机制

    首先,在x86架构的处理器上,一个正常页面大小为4KB,非PAE模式下,CR3持有页目录页面的物理地址,PDE和PTE格式相同大小为4字节.此时每个页表页面包含1024个PTE,可以映射1024个页面 ...

  2. 深入解析Windows操作系统笔记——CH3系统机制

    3.系统机制 微软提供了一些基本组件让内核模式的组件使用: 1.陷阱分发,包括终端,延迟的过程调用(DPC),异步过程调用(APC),异常分发以及系统服务分发 2.执行体对象管理器 3.同步,包括自旋 ...

  3. linux 逆向映射机制浅析

    2017-05-20 聚会回来一如既往的看了会羽毛球比赛,然后想到前几天和朋友讨论的逆向映射的问题,还是简要总结下,免得以后再忘记了!可是当我添加时间……这就有点尴尬了……520还在写技术博客…… 闲 ...

  4. 操作系统学习笔记(二) 页式映射及windbg验证方式

    页式映射 本系列截图来自网络搜索及以下基本书籍: <Windows内核设计思想> <Windows内核情景分析> <WINDOWS内核原理与实现> 一个32位虚拟地 ...

  5. Windows内核开发-6-内核机制 Kernel Mechanisms

    Windows内核开发-6-内核机制 Kernel Mechanisms 一部分Windows的内核机制对于驱动开发很有帮助,还有一部分对于内核理解和调试也很有帮助. Interrupt Reques ...

  6. MFC编程入门之五(MFC消息映射机制概述)

    在MFC软件开发中,界面操作或者线程之间通信都会经常用到消息,通过对消息的处理实现相应的操作.比较典型的过程是,用户操作窗口,然后有消息产生,送给窗口的消息处理函数处理,对用户的操作做出响应. 一.什 ...

  7. VS2010/MFC编程入门之五(MFC消息映射机制概述)

    VS2010/MFC编程入门之五(MFC消息映射机制概述)-软件开发-鸡啄米 http://www.jizhuomi.com/software/147.html 上一讲鸡啄米为大家简单分析了MFC应用 ...

  8. MFC消息映射机制

    1.MFC应用框架主要类之间的关系 MFC自动生成的框架中重要的类有:C-App.CMainFrame.C-Doc和C-View. 其他的类如CClassView.CFileView等都是在框架窗口( ...

  9. MFC的消息映射机制揭秘

    MFC的设计者们在设计MFC时,紧紧把握一个目标,那就是尽可能使得MFC的代码要小,速度尽可能快.为了这个目标,他们使用了许多技巧,其中很多技巧体现在宏的运用上,实现MFC的消息映射的机制就是其中之一 ...

随机推荐

  1. Objective-C中NSValue的使用

    我们在C/C++开发中常会用到结构体来帮助我们简单封装基本数据类型,在Objective-C中我们也可以使用结构体来完成数据类型的封装.同时,Cocoa Touch还提供了一个NSValue来帮助我们 ...

  2. NorFlash和NandFlash区别

      Flash编程原理都是只能将1写为0,而不能将0写成1.所以在Flash编程之前,必须将对应的块擦除,而擦除的过程就是将所有位都写为1的过程,块内的所有字节变为0xFF.因此可以说,编程是将相应位 ...

  3. Ubuntu 14.10 下安装SVN

    本文主要介绍SVN独立服务器的的安装和简单配置:1.安装 # sudo apt-get install subversion 测试安装是否成功: # svnserve --version 回车显示版本 ...

  4. Objective-c 命名规则

    1.方法名:第一个单词的首字母用小写,后面的单词首字母要大写<骆驼规则>,例如doSomething . doSomethingElse 2.类名:第一个单词的首字母要求大写,后面的单词首 ...

  5. How to Write Doc Comments for the Javadoc Tool

    http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html This document describe ...

  6. PHP中常用正则表达式大全

    常用正则表达式大全!(例如:匹配中文.匹配html) 匹配中文字符的正则表达式: [u4e00-u9fa5]    评注:匹配中文还真是个头疼的事,有了这个表达式就好办了 匹配双字节字符(包括汉字在内 ...

  7. Display Images in widget

    在自定义的widget中显示图片. 思路:定义类MyWidget,public 继承自QWidget,然后实现 void paintEvent(QPaintEvent *). 新建Empty qmak ...

  8. 头文件定义和ARM指令

    2015.2.2星期一,阴天 内存管理:内存的分配和释放等静态和动态内存:主要是在释放方式上的区别 静态变量:编译时就已经确定,定义在函数外面自动变量:在程序运行时才能在栈中确定只读数据节:存放常量的 ...

  9. LeetCode Combination Sum II (DFS)

    题意: 在集合candidates中选出任意多个元素,使得他们的和为target,返回所有的组合,以升序排列. 思路: 难点在于如何去重,比如集合{1,1,2},target=3,那么只有一个组合就是 ...

  10. OpenFlow Switch学习笔记(六)——Instructions和Actions

    本文主要重点讨论OpenFlow Switch规范的指令集,它们深刻影响着数据包在Switch中的处理行为,下面开始从以下几个部分谈起. 1.Instructions 每一个Flow Entry里都包 ...