浅谈windows页目录自映射

来源:互联网 发布:粒子滤波算法与卡尔曼 编辑:程序博客网 时间:2024/05/01 06:49

Windows的虚拟内存管理方案中,有一个设计很值得一提,那就是Windows页目录自映射机制

Windows用一个宏来实现给定一个PTE虚拟地址,可以返回这个PTE指向的页面的虚拟地址

这个宏是这样定义的

#define MiGetVirtualAddressMappedByPte(PTE)((PVOID)((ULONG)(PTE) << 10))

为了进一步理解这个宏为什么可以实现我们的从PTE映射到页面虚拟地址

我们首先看一下Windows的页面机制

Windows操作系统一般采用了分页机制,每页4k,因此32位的操作系统就有2^20个页面,因为页面过多,我们用页表来组织页面,每个页表同样也是一个页面,大小也为4k,每个页表由1024个宽度为32位的页表项组成,这样的话,2^2个页面就可以存储在2^10个页表中,这2^10个页表(这些页表也同样是页面)如何组织呢,我们仍然用一个页表把他们组织起来,刚好这个页表只用占用一个页面,因为已经使用过了页表这个名字,因此页表的页表就被称为了页目录。

一般大家在书上看应该都会看到以上的内容,但是没有讲一个概念,或者说没有强调一个概念,那就是其实每个页表其实也是一个页,页目录也是一个页表。

所以我们可以把系统中的1024×1024个页分为三类,第一类是普通的页,有1024×1023个,第二类是普通页表(不包括页目录)有1023个,第三类是页目录形式的页表,有1个。

因此总共有1024个页表,每个普通页表指向1024个普通页,对于页目录这个页表,它指向的1023个普通页就是第二类普通页表,另一个则是指向自己。

听起来似乎很绕口,但是实际上只要明白,页表也是页,页目录也是页表,每个页必须被某个页表指向。不论是被作为页表的页指向还是被作为页目录的页指向。



好了,到这儿我们就明白了Windows中的分页机制。

那么自映射又是什么情况呢。研究过Windows内核的人都知道,Windows的虚拟内存管理方案中,可以通过页面的虚拟地址PTE查询到这个PTE指向的页面的虚拟地址,再通过MMU可以转化为物理地址。

那怎样把PTE转化为虚拟地址呢?

我们刚刚看到了windows下页目录页被当作了一个页表来寻址4MB空间,初设计成这样的原因是windows为了节省4k的内存,但是却导致我们在。

windows在4G的虚拟内存空间中划分了一块地方存放所有的页表,一般情况下放置的位置就是CR3指向的位置,默认为0xc0000000到0x03fffff,一共为4MB,这一段空间正好为页目录所映射的1024个页表所在的区域(包含页目录)。

内存在映射的时候有几点规则

1.一个页表映射的4m虚拟地址肯定是连续的;

2.一个页表映射到的1024个4k的物理页不一定是连续的;

3.实现自映射必须是页目录和页表结构一样

有了以上的规则,我们要理解或者自己实现windows的自映射就必须理解windows的页表虚拟地址都是连续的,映射到0xc0000000到0xc03fffff表现为一个页表数组,一共1024项,每项4096个字节,正好4MB,页目录作为这4MB的页表。

反过来想,页目录成为了这4MB的页表,那么肯定映射到0xc0000000到0xc03fffff的地址,我们将两个端点分解开看

11000000000000000000000000000000B和11000000001111111111111111111111B

发现高10位都是相同的,而这高10位正好是768,说明这个页目录是页目录的第768项对应的页表,现在这个页目录可以作为一个页表插入到这个页表数组的第768项的位置了。CR3寄存器中写的是它的作为页目录的物理地址,同时,这个页目录的第768项写的也是这个页目录作为页表的物理地址。


原创粉丝点击