[转载]PAE下的虚拟内存映射 实践

转自:http://user.qzone.qq.com/31731705/blog/1323426728

前文是理论分析,在此: PAE下的虚拟内存映射 分析 (http://user.qzone.qq.com/31731705/blog/1323414733 ),理论需要结合实际,现在来实际体验一下。

随便选个进程,就当前进程吧,
0: kd> !process 
PROCESS 8da74d40  SessionId: 1  Cid: 1f6c    Peb: 7ffdf000  ParentCid: 19e4
    DirBase: deb6d0c0  ObjectTable: cce0d8b0  HandleCount: 216.
    Image: windbg.exe 
    VadRoot b11b89c8 Vads 106 Clone 0 Private 3601. Modified 0. Locked 0.
......

是Windbg进程,根据 上篇 中的介绍,0xC0603000的地方,指向了进程的页目录,而DirBase是deb6d0c0,是物理地址,也是指向PDPE的地址。它们的内容应该相同。

0: kd> dd c0603000 
c0603000  b21f0863 00000000 15ff1863 00000000
c0603010  55df2863 00000000 183f3863 00000000
......

开始处的4个值应该是4个PDE的物理地址,对应的VA分别是0xC0600000, 0xC0601000, 0xC0602000, 0xC0603000,让我们使用DirBase验证,

0: kd> !dd deb6d0c0 
#deb6d0c0 b21f0801 00000000 15ff1801 00000000
#deb6d0d0 55df2801 00000000 183f3801 00000000
......

乍一看,里面的值不一样, ,可以推断0xC0603000并没被映射到物理地址deb6d0c0,而是2块独立的内存。但是,地址处的值其实是一样的(因为最低的12Bit是属性值)。
进一步看看,
0: kd> !vtop deb6d0c0 c0600000 
X86VtoP: Virt c0600000, pagedir deb6d0c0
X86VtoP: PAE PDPE deb6d0d8 - 00000000183f3801
X86VtoP: PAE PDE 183f3018 - 00000000183f3863
X86VtoP: PAE PTE 183f3000 - 00000000b21f0863
X86VtoP: PAE Mapped phys b21f0000
Virtual address c0600000 translates to physical address b21f0000 .
0: kd> !vtop deb6d0c0 c0601000 
X86VtoP: Virt c0601000, pagedir deb6d0c0
X86VtoP: PAE PDPE deb6d0d8 - 00000000183f3801
X86VtoP: PAE PDE 183f3018 - 00000000183f3863
X86VtoP: PAE PTE 183f3008 - 0000000015ff1863
X86VtoP: PAE Mapped phys 15ff1000
Virtual address c0601000 translates to physical address 15ff1000 .
0: kd> !vtop deb6d0c0 c0602000 
X86VtoP: Virt c0602000, pagedir deb6d0c0
X86VtoP: PAE PDPE deb6d0d8 - 00000000183f3801
X86VtoP: PAE PDE 183f3018 - 00000000183f3863
X86VtoP: PAE PTE 183f3010 - 0000000055df2863
X86VtoP: PAE Mapped phys 55df2000
Virtual address c0602000 translates to physical address 55df2000 .
0: kd> !vtop deb6d0c0 c0603000 
X86VtoP: Virt c0603000, pagedir deb6d0c0
X86VtoP: PAE PDPE deb6d0d8 - 00000000183f3801
X86VtoP: PAE PDE 183f3018 - 00000000183f3863
X86VtoP: PAE PTE 183f3018 - 00000000183f3863
X86VtoP: PAE Mapped phys 183f3000
Virtual address c0603000 translates to physical address 183f3000 .

确实验证了前面的分析结果,VA 0xC0603000或者物理地址deb6d0c0处的值,分别对应着4个VA(0xC0600000, 0xC0601000, 0xC0602000, 0xC0603000)的物理地址。如果你够细心,你会发现0xC0603000处的内容指向了它自己(结合 上一篇 中的图),这真的很神奇。这样,任何进程都可以通过线性地址访问页目录指针表,页目录,页表,还有普通的内存页。

回到开始,为什么DirBase的值,不是0xC0603000的物理地址183f3000,而是另外的一块deb6d0c0(对应的虚拟地址VA是0x8856d0c0)。

0: kd> !vtop deb6d0c0 0x8856d0c0 
X86VtoP: Virt 8856d0c0, pagedir deb6d0c0
X86VtoP: PAE PDPE deb6d0d0 - 0000000055df2801
X86VtoP: PAE PDE 55df2210 - 00000000dea009e3
X86VtoP: PAE Large page mapped phys deb6d0c0
Virtual address 8856d0c0 translates to physical address deb6d0c0.

是一个Large Page,在PAE下这是1个2M的Page,先Hold住这个问题, 切换到另外一个进程看看,

0: kd> !process 0 0 qq.exe 
PROCESS 887a4d40  SessionId: 1  Cid: 029c    Peb: 7ffd6000  ParentCid: 17c0
    DirBase: dc99dac0  ObjectTable: be517450  HandleCount: 2125.
    Image: QQ.exe
0: kd> .process /p /r 887a4d40 
Implicit process is now 887a4d40
Loading User Symbols
................................................................
看看QQ进程的情况,
0: kd> !dd dc99dac0 
#dc99dac0 acec1801 00000000 a92c2801 00000000
#dc99dad0 9dcc3801 00000000 a95c4801 00000000
#dc99dae0 8a79df20 8495ec20 38eb2801 00000000
......
0: kd> dd c0603000 
c0603000  acec1863 00000000 a92c2863 00000000
c0603010  9dcc3863 00000000 a95c4863 00000000
c0603020  b07c5863 00000000 00000000 00000000
......
同样,0xC0603000没有被映射到DirBase: dc99dac0上,但前4项的内容是一致的,是QQ进程的PDE的物理地址,
0: kd> !vtop dc99dac0 c0600000; !vtop dc99dac0 c0601000; !vtop dc99dac0 c0602000; !vtop dc99dac0 c0603000; 
X86VtoP: Virt c0600000, pagedir dc99dac0
X86VtoP: PAE PDPE dc99dad8 - 00000000a95c4801
X86VtoP: PAE PDE a95c4018 - 00000000a95c4863
X86VtoP: PAE PTE a95c4000 - 00000000acec1863
X86VtoP: PAE Mapped phys acec1000
Virtual address c0600000 translates to physical address acec1000 .
X86VtoP: Virt c0601000, pagedir dc99dac0
X86VtoP: PAE PDPE dc99dad8 - 00000000a95c4801
X86VtoP: PAE PDE a95c4018 - 00000000a95c4863
X86VtoP: PAE PTE a95c4008 - 00000000a92c2863
X86VtoP: PAE Mapped phys a92c2000
Virtual address c0601000 translates to physical address a92c2000 .
X86VtoP: Virt c0602000, pagedir dc99dac0
X86VtoP: PAE PDPE dc99dad8 - 00000000a95c4801
X86VtoP: PAE PDE a95c4018 - 00000000a95c4863
X86VtoP: PAE PTE a95c4010 - 000000009dcc3863
X86VtoP: PAE Mapped phys 9dcc3000
Virtual address c0602000 translates to physical address 9dcc3000 .
X86VtoP: Virt c0603000, pagedir dc99dac0
X86VtoP: PAE PDPE dc99dad8 - 00000000a95c4801
X86VtoP: PAE PDE a95c4018 - 00000000a95c4863
X86VtoP: PAE PTE a95c4018 - 00000000a95c4863
X86VtoP: PAE Mapped phys a95c4000
Virtual address c0603000 translates to physical address a95c4000 .

转换过程和前面一样,4个PDE分别对应着QQ进程的虚拟地址VA 0xC0600000, 0xC0601000, 0xC0602000, 0xC0603000。
这个实验也证明了另一点,页表是进程相关的,即使0xC0X00000是位于内核态的地址,随着进程的切换也会被映射到不同的物理地址上。(这打破了我以前的一个假设,之前我并没想这么多,而是简单的认为内核只有一个,里面的对象都是共享的,进程无关的,现在看来至少页表不是。 )

再来看看开始的那个问题, 0xC0603000对应的并不是DirBase表示的物理地址,为什么呢?

我并没有确切的答案, 猜想是这样,象鸡和蛋的关系,要将虚拟地址转化成为物理地址,必须要有一个物理地址作为引子,也需要PDE的物理地址,这是必需且没有办法避免的。如何访问到那些PDE呢?通过0xC0603000是行不通的,因为那是虚拟地址,本身就需要转换,并且是代表着当前进程的页表,是进程相关的,所以需要一个进程无关的,系统全局的数据来储存这些数据,这些就是DirBase。内核可以通过这些数据来转化虚拟地址,切换进程,访问各个进程的地址空间。

那么,另一个问题是, DirBase为什么不使用各个进程?中0xC0603000对应的物理地址? 比如以Windbg和QQ为例,DirBase分别是183f3000和a95c4000。

我还是不知道答案, ,推测进程的页表会随着进程的切换而切换,而183f3000和a95c4000这2个物理页有可能被切换出去,这时它其中的值就没有意义了。而现在的值deb6d0c0和dc99dac0,这2个物理页应该是常驻物理内存的那种,这样内核可以在任何时候访问进程的PDE。

看看Windbg进程DirBase: deb6d0c0(对应的虚拟地址VA是0x8856d0c0),当前的进程已经切换成了QQ进程,

0: kd> !vtop dc99dac0 8856d0c0 
X86VtoP: Virt 8856d0c0, pagedir dc99dac0
X86VtoP: PAE PDPE dc99dad0 - 000000009dcc3801
X86VtoP: PAE PDE 9dcc3210 - 00000000dea009e3
X86VtoP: PAE Large page mapped phys deb6d0c0
Virtual address 8856d0c0 translates to physical address deb6d0c0 .

可以清楚的看到,即使使用了QQ进程的DirBase,这个虚拟地址对应的内容还是deb6d0c0,没有变化。

再看看QQ进程的DirBase: dc99dac0(对应的虚拟地址是8a79dac0)。
0: kd> !vtop dc99dac0 8a79dac0 
X86VtoP: Virt 8a79dac0, pagedir dc99dac0
X86VtoP: PAE PDPE dc99dad0 - 000000009dcc3801
X86VtoP: PAE PDE 9dcc3298 - 00000000dc8009e3
X86VtoP: PAE Large page mapped phys dc99dac0
Virtual address 8a79dac0 translates to physical address dc99dac0 .

使用Windbg进程的DirBase测试一下,
0: kd> !vtop deb6d0c0 8a79dac0 
X86VtoP: Virt 8a79dac0, pagedir deb6d0c0
X86VtoP: PAE PDPE deb6d0d0 - 0000000055df2801
X86VtoP: PAE PDE 55df2298 - 00000000dc8009e3
X86VtoP: PAE Large page mapped phys dc99dac0
Virtual address 8a79dac0 translates to physical address dc99dac0 .

可见,这些DirBase的内存页是进程无关,系统共享的,只需要知道这些DirBase,就能够顺藤摸瓜,找到所有进程的PDE,进而确认所有进程的页表。

时间: 2024-10-12 17:19:32

[转载]PAE下的虚拟内存映射 实践的相关文章

[转载]PAE下的虚拟内存映射 分析

转自:http://user.qzone.qq.com/31731705/blog/1323414733 PAE 即为物理地址扩展(Physical Address Extension),详细的内容请Google. 我的电脑是Win7,CPU是双核处理器,信息如下, 0: kd> !sysinfo cpuinfo  [CPU Information] ~MHz = REG_DWORD 2527 Component Information = REG_BINARY 0,0,0,0,0,0,0,0,

分布式架构下的会话追踪实践【基于Cookie和Redis实现】

分布式架构下的会话追踪实践[基于Cookie和Redis实现] 博客分类: NoSQL/Redis/MongoDB session共享rediscookie分布式架构session 在单台Tomcat应用中,通常使用session保存用户的会话数据.面对高并发的场景,一台Tomcat难当大任,通常我们会使用Nginx在前端拦截用户请求,转发给后端的Tomcat服务器群组.在集群环境下,怎么才能做到session数据在多台Tomcat之间的共享呢? 当然我们可以在多台Tomcat之间进行sessi

读生产环境下go语言最佳实践有感

最近看了一篇关于go产品开发最佳实践的文章,go-in-procution.作者总结了他们在用go开发过程中的很多实际经验,我们很多其实也用到了,鉴于此,这里就简单的写写读后感,后续我也争取能将这篇文章翻译出来.后面我用soundcloud来指代原作者. 开发环境 在soundcloud,每个人使用一个独立的GOPATH,并且在GOPATH直接按照go规定的代码路径方式clone代码. $ mkdir -p $GOPATH/src/github.com/soundcloud $ cd $GOPA

[转载] linux下打开windows txt文件中文乱码问题

原文链接 在linux操作系统下,我们有时打开在windows下的txt文件,发现在windows下能正常显示的txt文件出现了中文乱码. 出现这种情况的原因为两种操作系统的中文压缩方式不同,在windows环境中中文压缩一般为gbk,而在linux环境中为utf8,这就导致了在windows下能正常显示 txt文件在linux环境下打开呈现了乱码状态. 解决方法:在linux用iconv命令,如乱码文件名为shujujiegou.txt,那么在终端输入如下命令: iconv -f gbk -t

[转载]Ubuntu下arm-linux-gdb+gdbserver的编译及安装

原文地址:Ubuntu下arm-linux-gdb+gdbserver的编译及安装作者:136*****[email protected] 注:arm-linux-gdb的安装路径是/usr/local/arm/3.4.11.arm-linux-gdb的编译安装下载gdb-6.8.tar.bz2至工作目录 gdb源码下载:http://ftp.gnu.org/gnu/gdb/ 命令如下: $tar -jxvf gdb-6.8.tar.bz2$cd gdb-6.8$./configure --ta

自己总结的C#编码规范--3.特定场景下的命名最佳实践

特定场景下的命名最佳实践 命名空间 要使用PascalCasing,并用点号来分隔名字空间中的各个部分. 如Microsof.Office.PowerPoint 要用公司名作为命名空间的前缀,这样就可以避免与另外一家公司使用相同的名字. 要用稳定的,与版本无关的产品名称作为命名空间的第二层 不要使用公司的组织架构来决定命名空间的层次结构,因为内部组织结构经常改变. 不要用相同的名字来命名命名空间和该空间内的类型. 例如,不要先将命名空间命名为Debug,然后又在该空间中提供Debug类.大部分编

[转载]Windows下的分页模式- 页目录和页表从物理内存到虚拟映射求值

标 题: [原创]Windows下的分页模式-  页目录和页表从物理内存到虚拟映射求值 作 者: hrpirip 时 间: 2012-12-06,12:45:36 链 接: http://bbs.pediy.com/showthread.php?t=159554 昨天在网上看到一段代码令大为不解,大家都知道一个虚拟地址到物理地址的转换伪公式为:*(*(*PD[(VirtualAddress>>22)] & FFFFF000) [(VirtualAddress & 3FF000)

[转载]PAE ( Physical Address Extension )

转自:http://blog.chinaunix.net/uid-20384269-id-1954602.html 首先,内存访问和管理是一个跨越应用程序,操作系统,硬件平台的一个复杂过程,不能单纯的讲32bit系统就支持4G内存,从而认为这个过程只是OS和内存两者之间的关系 理论上:32位系统,32bit的地址总线位数,寻址空间2^32B=4GB. 64位系统,寻址空间2^64. 至于在实际应用环境中,对于有4G物理内存而OS最多只能识别3G的情况,主要是主板的问题,丢掉的内存被PCI设备占用

Linux下的socket编程实践(十) 基本UDP编程细节

在我的这两篇博客中,简单介绍并实现了基于UDP(TCP)的windows(UNIX下流程基本一致)下的服务端和客户端的程序,本文继续探讨关于UDP编程的一些细节. http://blog.csdn.net/nk_test/article/details/47733307 http://blog.csdn.net/nk_test/article/details/47756381 下图是一个简单的UDP客户/服务器模型: 我在这里也实现了一个简单的UDP回射服务器/客户端: /**实践: 实现一个基