首先,在x86架构的处理器上,一个正常页面大小为4KB,非PAE模式下,CR3持有页目录页面的物理地址,PDE和PTE格式相同大小为4字节。此时每个页表页面包含1024个PTE,可以映射1024个页面。而x86的4GB地址空间共包含1M个4KB的页面,映射所有这些页面共需要1024个页表页面,映射这1024个页表页面又需要1个页目录页面。乍看起来我们一共需要1025个页面来管理1M个页面的映射,其实不然。

我们不妨逆向理顺一下思路。首先,我们的地址空间中有1M=1024x1024个页面,而一个页表页面可以映射1024个页面。所以,我们把4GB地址空间的1M个页面按每1024个页面分为1024组。映射这1024组页面正好需要1024个页表页面,所以我们从刚才的1024组页面中拿掉一组用作页表。刚才的页面还剩下1023组,会消耗掉我们这组页表页面中的1023个用来映射。所以我们这组页表页面中还剩下一个,我们用它来映射刚刚的1023个页表页面,从而消耗掉了1023个Entry,那剩下的1个Entry呢?用来映射最后这个页面本身。

这样分配听起来似乎清晰多了,能实现吗?按上面的思路,最后一个页表页面无疑是要用作页目录。x86处理器MMU访问线性地址是要经过两次查找加一个偏移(非PAE模式)来确定物理地址的。以此为基础,通过页目录、页表、再加上偏移访问那1023组页面很好理解,但是如何在线性地址中访问1023个页表页面及页目录页面呢?也就是如何通过页目录页面把1023个页表页面和页目录页面自身映射到线性地址中。其实这就是32位Windows的页表自映射机制。

在32位的Windows中,页表的起始线性地址恒为0xC0000000,整个页表区域占用了连续的4MB线性地址空间。最关键的一个设计,就是页目录的第0x300项Entry指向页目录本身,进而也就决定了页目录页面的线性地址为0xC0300000。这一设计使得MMU在查找0xC0000000~0xC03FFFFF这一线性地址空间内的任一线性地址的物理地址时,会把页目录页面当做页表页面来使用,也就是说会访问页目录页面两次。如下图,是微软2004年在东京大学举办Windows Kernel Internals讲座解释GetPteAddress原理时所给出的一张图示:

其实GetPteAddress功能就是给定一个线性地址,得出用以映射这个线性地址所属页面的PTE的地址。原理很明了,4GB的地址空间中包含1M个页面,而4MB的页表区域包含1MB个PTE,这些PTE正是按顺序一一对应了所有这些页面。所以把整个地址空间看作是页面的数组,可以很轻松计算出某个线性地址所属页面的索引,例如0xE4321000>>12=0xE4321,而PTE数组中对应PTE的线性地址即为0xC0000000+(0xE4321<<2)=0xC0390C84。

由上图可以看出,给定的线性地址的高10位为1100000000=0x300,即MMU转译线性地址的第一步:在页目录页面中查找页表指针时使用的索引为0x300,从而使MMU得到页目录页面本身的物理地址。因此MMU在第二个步骤:在页表页面中查找最终的页面指针时,会使用页目录页面作为页表页面以供查找。而页目录页面的所有1024个Entry存储的是其本身和其他1023个页表页面的物理地址,所以MMU经过两次查找最终得到的是某个页表页面的物理地址。当线性地址的高10位固定为1100000000时,剩余低22位仅能表示4MB的范围,因此其所能表示的线性地址限定在0xC0000000~0xC03FFFFF这一区间内,也正是所有页表页面所占用的线性地址空间范围。因为微软所给出的图示适是用于讲解PTE的,PTE大小为4字节并且其地址也是4字节对齐,所以最后的12位页面内偏移也可以理解为利用前10位用作PTE数组索引,最低2位恒为0。

不难想到当MMU第二步查找时如果仍然使用0x300索引,也就是线性地址高20位为11000000001100000000,那么MMU经过两次查找最终得到的物理地址就是页目录页面的物理地址,如下图:

再加上最低12位的页面内偏移, MMU最终转译得到的地址落在页目录页面内,也就是说线性地址0xC0300000~0xC0300FFF表示的区间范围即为页目录页面在线性地址中的地址区间范围。如果在12位的页面偏移中,继续使高10位为1100000000用作PTE索引,那么得到的就是指向页目录自身的PTE,也是PDE,其线性地址为0xC0300C00。

总结,使用一个页面用作页目录,使它的第0x300个Entry指向其自身,剩余的1023个Entry指向其他的1023个页表页面。从而巧妙的将页表区间映射到0xC0000000~0xC03FFFFF这一线性地址区间。

x86平台上的Windows页表映射机制的更多相关文章

  1. 运行在TQ2440开发板上以及X86平台上的linux内核编译

    一.运行在TQ2440开发板上的linux内核编译 1.获取源码并解压 直接使用天嵌移植好的“linux-2.6.30.4_20100531.tar.bz2”源码包. 解压(天嵌默认解压到/opt/E ...

  2. OpenStack平台上,windows云主机可以ping通百度但是无法打开网页,部分其它网页可以打开

    问题描述: 在OpenStack平台上的64位Windows7虚拟机,可以ping通百度,但是却无法打开百度网页. 于是,笔者又对其它网址进行的测试,发现淘宝.京东.携程部分网页可以打开,而新浪等等网 ...

  3. windows的页自映射机制

    windows下由于启用了页机制,所有软件层面的地址操作都是VA,通过descriptor(base address(32bit))+offset得到的线性地址并不直接对应物理地址,而是经过页转换机构 ...

  4. 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件

    本文背景: 在编程中,很多Windows或C++的内存函数不知道有什么区别,更别谈有效使用:根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制. 本 ...

  5. Windows平台上Caffe的训练与学习方法(以数据库CIFAR-10为例)

    Windows平台上Caffe的训练与学习方法(以数据库CIFAR-10为例) 在完成winodws平台上的caffe环境的搭建之后,亟待掌握的就是如何在caffe中进行训练与学习,下面将进行简单的介 ...

  6. Java平台上的AOP实现机制

    Java平台上的AOP实现机制 动态代理(Dynamic Proxy)机制,在运行期间动态的为相应接口生成对应的代理对象.SpringAop默认情况下采用这种机制来实现AOP机能.缺点:相对于编译后的 ...

  7. KVM基于X86硬件辅助的虚拟化技术实现机制【转】

    内存虚拟化 Shadow Paging 作者 Shawn 在其中文博客中很详尽地介绍了 KVM 在只支持一级分页的 x86 平台上用 “Shadow Paging”进行 MMU 虚拟化的实现,由于目前 ...

  8. Linux平台上DPDK入门指南

    1. 简介 本文档包含DPDK软件安装和配置的相关说明.旨在帮助用户快速启动和运行软件.文档主要描述了在Linux环境下编译和 运行DPDK应用程序,但是文档并不深入DPDK的具体实现细节. 1.1. ...

  9. linux 逆向映射机制浅析

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

随机推荐

  1. 墨卡托投影坐标系(Mercator Projection)原理及实现C代码

    墨卡托投影是一种"等角正切圆柱投影",荷兰地图学家墨卡托(Mercator)在1569年拟定:假设地球被围在一个中空的圆柱里,其赤道与圆柱相接触,然后再假想地球中心有一盏灯,把球面 ...

  2. Mybatis Mapper.xml 需要查询返回List<String>

    当需要查询返回 List<String> <select id="getByIds" parameterType="java.lang.String&q ...

  3. servlet的运行工作

    我是一个刚学几天的小白,写得不好,如果哪个地方有错误,欢迎你们指出. 在服务器端,我用的是Tomcat作为Servlet 容器,在容器中有一个Servlet接口,你编写一个servlet类放在Tomc ...

  4. mybatis like 的坑

    昨天快要下班的时候组长交代了一个任务,说起来很简单,是这样的: 系统里面有一个字段为name,这个name允许设置为特殊字符,目前根据name模糊匹配,如果遇到特殊字符 比如 "$" ...

  5. How to use VisualSVN Server and TortoiseSVN to host your codes and control your codes' version

    ###############################   PART ONE   ############################### #1. Introduction of the ...

  6. DOM Exception error 类型

    INDEX_SIZE_ERR  code 1                              索引是负值,或者超过了索引值 DOMSTRING_SIZE_ERR  code 2       ...

  7. Flexbox 布局教程

    Flex 布局是什么? Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性. 任何一个容器都可以指定为 Flex 布局. 使用 fle ...

  8. asp.net后台发送HTTP请求

    一.文件流方式(转自:http://blog.csdn.net/u011511086/article/details/53216330) /// 发送请求 /// </summary> / ...

  9. 必须先将 ContentLength 字节写入请求流,然后再调用 [Begin]GetResponse。解决方法

    当在后台实现POST请求的时候,出现如下错误: 必须先将 ContentLength 字节写入请求流,然后再调用 [Begin]GetResponse. 或者是如下错误: 上述是因为由于我们使用的是代 ...

  10. C#操纵Excel,此工作薄包含嵌入对象,Office 2007的设定方法

    C#操纵Excel,插入OLE对象时报“此工作薄包含嵌入对象,EXCEL可能无法从这些对象中删除个人信息.”, 如网上所述,Office 2003可以通过“菜单>>工具>>选项 ...