首先,在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. 图片首尾平滑轮播(JS原生方法—节流)<原创>

    首先给出HTML代码,要注意轮播图片表(#list)末尾加上第一个图片1.jpg,在首部加上最后一个图片5.jpg. <!DOCTYPE html> <html lang=" ...

  2. PE格式第九讲,资源表解析

    PE格式第九讲,资源表解析 一丶熟悉Windows管理文件的方法 首先,为什么标题是这个,主要是为了下边讲解资源方便,因为资源结构体很乱.如果直接拿出来讲解,那么就会很晕. 1.windows管理文件 ...

  3. 多平台Native库打入JAR包发布实战

    1.前言 在开发Java应用的过程中,经常会遇到需要使用C/C++等Native语言编译的动态库或静态库,在这些情况下往往需要将预先编译好的各平台库文件与JAR包一同发布,鉴于简洁的原则,我们可能会希 ...

  4. 【ASP.NET MVC 学习笔记】- 09 Area的使用

    本文参考:http://www.cnblogs.com/willick/p/3331519.html 1.ASP.NET MVC允许使用 Area(区域)来组织Web应用程序,这对于大的工程非常有用, ...

  5. java:利用静态字段和构造函数实现已建对象数查询

    问题:使用类的静态字段和构造函数,我们可以跟踪某个类所创建对象的个数. 请写一个类,在任何时候都可以向它查询"你已经创建了多少个对象?". 程序设计思想: 利用静态变量指定一个计数 ...

  6. Vim - 常用配置

    基本配置 不用任何插件的情况下,先按如下配置: set nu syntax on set hlsearch set tabstop=4 set shiftwidth=4 set expandtab s ...

  7. 阿里云ubuntu安装jdk8+mysql+tomcat

    Mysql安装 使用apt-get安装 apt-get install mysql-server apt-get install mysql-client apt-get install libmys ...

  8. 使用selenium webdriver+beautifulsoup+跳转frame,实现模拟点击网页下一页按钮,抓取网页数据

    记录一次快速实现的python爬虫,想要抓取中财网数据引擎的新三板板块下面所有股票的公司档案,网址为http://data.cfi.cn/data_ndkA0A1934A1935A1986A1995. ...

  9. 通过 ODBC 访问数据库获取数据集

    Step1:(window 中完成): 控制面板/管理工具/ODBC 数据源/用户 Step2:(window 中完成): 添加/SQL Server Step3:(window 中完成): 自己定义 ...

  10. grunt-contrib-connect自动刷新html页面

    grunt-contrib-connect可以在我们开发的时候自动刷新页面,省去了手动刷新的时间. 下面说一下如何配置grunt-contrib-connect 1.下载插件包 npm install ...