tiamo
VIP专家组
VIP专家组
  • 注册日期2002-02-26
  • 最后登录2018-01-09
  • 粉丝17
  • 关注4
  • 积分50分
  • 威望142点
  • 贡献值1点
  • 好评度40点
  • 原创分2分
  • 专家分15分
  • 原创先锋奖
  • 社区居民
阅读:4294回复:5

pde pte 及其他

楼主#
更多 发布于:2004-05-18 19:19
关于pde pte就不多说了
直接进入主题........

代码当然是windows 2000的源代码了
自己的系统是windows server 2003
p4 2.4g 不使用pae

先介绍一个比较重要的东西,就是PFN,page frame number,他代表了一个物理页,系统里面全部的PFN组成一个数组,他的首地址由MmPfnDatabase给出,这个数组的每一个项代表了一个物理页,物理页按照地址从低到高赋予一个下标,这个下标就用来索引MmPfnDatabase数组.
关于MMPFN的定义在private\\ntos\\mm\\mi.h文件里面.

这个database是用来干什么的呢?他是用来把一个物理页映射成回一个pte的.

每个进程的pde和pte的线性地址都是相同的,pde的开始地址是PDE_BASE = 0xc0300000,pte的线性地址是PTE_BASE = 0xc0000000,用si看看这两个线性地址就能看到整个进程的全貌.

windows 2000为每个进程保留了3M+4K的空间用于放硬件进程描述表相关的数据(只是硬件相关),为什么不是4M + 4K呢?因为其中有一部分的pte是指向系统的pte,为什么不是2M呢?因为windows支持3G的user space.

进程的大部分描述表是在进程创建的时候设置的.进程创建经过多个函数的调用来到PspCreateProcess(\\private\\ntos\\ps\\create.c)函数,这个函数调用MmCreateProcessAddressSpace(\\private\\ntos\\mm\\procsub.c)函数完成地址空间的创建工作.重点也就在这个函数里面了,去掉那些诸如_X86_PAE_的ifdef语句看起来估计会比较轻松一点.

经过一系列的检查工作以后,它获取了一个Zero的page(C2安全要求)(MiRemoveZeroPageIfAny或者MiRemoveZeroPage),这个page用来放进程的pde,这两个获取的函数返回的值就是物理页的下标,它填充到了DirectoryTableBase[0]里面(宏INITIALIZE_DIRECTORY_TABLE_BASE把下标左移12位),然后再获取了一个物理页,这个page用来作进程的hyperspace页(这个页的作用下面会讲到).又使用宏INITIALIZE_DIRECTORY_TABLE_BASE填充到DirectoryTableBase[1]里面(最终这个DirectoryTableBase会复制到新创建的进程的KPROCESS里面).这里获取的两个page都是用0填充的,还不能使用,接下来的任务就是填充这个两个page.

先停一下,这个时候的进程空间还是原来的那个(也就是调用CreateProcess的进程),这个时候的cr3还是原来的cr3,page table也是原来的page table,如果我们要设置新的page table怎么办?记着设置page table是要访问物理内存的,windows并没有一个通用的page table访问物理内存,怎么办呢?这就是hyperspace的一个作用了,它用来临时的映射物理内存,这个工作是由MiMapPageInHyperSpace(\\private\\ntos\\mm\\i386\\hypermap.c)完成的.这个函数很简单,在进程里面保留了一些page table entry,这些entry是invalid,这个时候把他们变成有效的,然后设置好物理页的地址就能使用了.这些保留的page table entry构成一个数组链表,它由MmFirstReservedMappingPte指出链表的头,用它的PageFrameNumber域表示当前空闲的链表的下标,这样每次把下标减1,然后索引到原来的那个空闲节点,把新的节点的PageFrameNumber设置成要访问的物理页然后更新这个pte就能访问物理内存了,在函数返回的时候获取了访问该物理内存的线性地址.这里不能不说一下进程的page table的结构了.因为这个函数的行为是很奇怪的.它直接把pte的地址左移了10位.

进程的page entry table从线性地址PTE_BASE = 0xc0000000开始,每4个字节表示了一个线性地址页,同时windows 让线性地址和页下标一一对应,也就是说
c0000000 <-> 00000000 - 00001000
c0000004 <-> 00001000 - 00002000
.......

这样把pte的线性地址左移动10位就得到了它代表的线性页的起始地址.细心的朋友可能已经发现了
PDE_BASE = c0300000 <-> PTE_BASE = c0000000
正好是page table的开始地址,这个后面马上就讲到.

再回来,原进程在自己的hyperspace里面建立了一个pte用来访问这个新创建的page,并且返回了用于访问新创建的page的的线性地址.
接下来的事情就简单了,建立pde,注意,这里只是建立了pde,为什么?因为我们只是映射了新创建的用于放page directory的物理页.

那这个物理页里面都要填些什么东西了?首先,填入了hyperspace的pde,然后是page dir自己的pde,这两个操作都非常简单,调用MiGetPdeOffset函数获取到一个offset,然后索引到刚刚获得的线性地址,然后设置pte就ok.看起来是很简单,但是里面包含的含义就复杂了.先看MiGetPdeOffset函数返回的是什么,它定义在\\private\\ntos\\mm\\i386\\mi386.h里面,返回的就是一个线性地址对应的pde的下标.用它作为索引来索引pde数组.hyperspace的起始page是HYPER_SPACE = 0xc0400000.我们用这个线性地址访问到的物理地址应该是刚刚创建的hyperspace 的 page,这里windows让这个page的pde(下标0x301)地址等于它的pte地址(填的就是hyperspace的pde的地址),这样节省一个 pde 出来.page table的设置的操作也是一样的,PTE_BASE = 0xc0000000 它对应的pde的下标是0x300,现在把pde[0x300] = page dir table的物理地址,这样访问page table 的时候得到的pte就是page dir table的地址,也就是说对于 page table的pde和pte是同一个东西,这样合在一起有什么好处呢?关键就在于交换的部分了,如果放的pte的页要被交换到文件里面去了,就必须要更新pde的值,怎么办?也就必须要建立pte和pde的对应关系,但是现在,因为pde和pte是同一个东西,这样修改pte的同时其实也就修改了pde,这样就不用额外的对应数据结构了,那普通的物理页交换呢?这个工作就是由MmPfnDataBase完成了,它里面保存了一个pte的指针.

ok,明白这个了以后,再看下面的操作就更加的简单了.
设置内核使用的pde(这个是每个进程都相同的),它使用MiGetPdeAddress(\\private\\ntos\\mm\\i386\\mi386.h)函数获取pde的线性地址(pde也是和pte一样有一一对应的关系),它把原进程的pde复制一份到新的进程.到此 pde和pte的初始设置就完成了.

呃...
还有最后一个问题.刚刚提到那个访问新的物理页使用的是hyperspace的pte,这个pte是什么时候设置的呢?关键就在于MmFirstReservedMappingPte这个变量,瞧瞧,它等于0xc0301000,手动作作转换看看pde index = 0x300,pte的线性地址是0xc0300000(记得么,page table的pde和pte是重叠的)pte index = 0x301,哈哈,原来这个物理页就是hyperspace本身(还记得hyperspace的设置么).原来这个pte早就是准备好了的,它的内容呢?全部是0(因为hyperspace是一个zero过的page).....

今天要说的就完了..不知道大家能不能看明白....

最新喜欢:

asdfslwasdfsl...
rock1001
驱动牛犊
驱动牛犊
  • 注册日期2002-11-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-05-19 08:45
好贴 :D
我没看明白
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
板凳#
发布于:2004-05-19 12:33
tiamo兄的帖子,说什么也要顶,嘿嘿......
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
Sephiroth
驱动牛犊
驱动牛犊
  • 注册日期2003-05-03
  • 最后登录2005-09-01
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-05-26 18:49
不要让一堆垃圾贴子淹了一篇好文章
MTE.EA
驱动牛犊
驱动牛犊
  • 注册日期2003-11-12
  • 最后登录2023-02-21
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-05-26 18:53
不要让一堆垃圾贴子淹了一篇好文章

是啊
最近垃圾帖好多
源代码讨论版成啥了
linestyle
驱动小牛
驱动小牛
  • 注册日期2004-01-28
  • 最后登录2010-01-05
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望139点
  • 贡献值0点
  • 好评度135点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-09-13 15:18
支持!:)
loading is waiting ...
游客

返回顶部