嘿嘿,简单打几个字,给这个优秀帖丰富点儿内容.
#define PTE_BASE 0xC0000000 #define PDE_BASE 0xC0300000
根据
虚拟地址 得到
PTE 的地址和
PDE 的地址:
#define GetPteAddress(va) ((PMMPTE)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE)) #define GetPdeAddress(va) ((PMMPTE)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE))
------------------------------------------------------------------------------------------------------
再看看
pte 的结构:
lkd> dt nt!_hardware_pte nt!_HARDWARE_PTE +0x000 Valid : Pos 0, 1 Bit +0x000 Write : Pos 1, 1 Bit +0x000 Owner : Pos 2, 1 Bit +0x000 WriteThrough : Pos 3, 1 Bit +0x000 CacheDisable : Pos 4, 1 Bit +0x000 Accessed : Pos 5, 1 Bit +0x000 Dirty : Pos 6, 1 Bit +0x000 LargePage : Pos 7, 1 Bit +0x000 Global : Pos 8, 1 Bit +0x000 CopyOnWrite : Pos 9, 1 Bit +0x000 Prototype : Pos 10, 1 Bit +0x000 reserved : Pos 11, 1 Bit +0x000 PageFrameNumber : Pos 12, 20 Bits
PTE和PDE的格式实际上是一样的 。
PTE
+---------------+---------------+---------------+---------------+
|3 3 2 2 2 2 2 2|2 2 2 2 1 1 1 1|1 1 1 1 1 1 | |
|1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
+---------------------------------------+-----------------------+
| |T P C U R D A P P U R P|
| Base address 20 bits |R P W C W S W |
| |N T D T |
+---------------------------------------+-----------------------+
还有个概念是
pfn :
lkd> !pfn
PFN 00000000 at address 8178A000
flink 00000000 blink / share count 00000000 pteaddress 00000000
reference count 0000 NonCached color 0
restore pte 00000000 containing page 000000 Zeroed
...
这些东西在俄罗斯一大牛05年写的"
内存与进程管理器 "有部分介绍. 把内容传上来了,见附件
另外给篇资料供大家参考 -->
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(转载,原始出处:
http://stonefish99.spaces.live.com/blog/cns!8D0306EAAFBB673C!118.entry )
关于PTE/PDE
上节课老师讲了关于PDE,PTE的虚拟地址计算的一些内容,当时有点晕,主要是两个问题:1 虚拟地址到物理地址的转换必须用到PDE,PTE的虚拟地址吗?是怎么转换的?2 计算PDE,PTE的虚拟地址有什么用?回来做了一些实验,终于明白了,下面是一些实验结果
一 虚拟地址如何转换到物理地址?必须用到PDE,PTE的虚拟地址吗?
按照以前学习的分页机制,一个虚拟地址转换成物理地址的计算过程应该是:
1 处理器通过CR3找到当前页目录所在的物理页地址a
2 计算PDE的物理地址:a+ 虚拟地址高十位左移两位 (因为每个页目录项四个字节),取出该地址处的PDE,PDE的前20位+低12位0是这个虚拟地址对应页表的物理地址b
3 计算PTE的物理地址:b+ 虚拟地址的中间10位左移两位,取出该地址处的PTE,PTE的前20位是这个虚拟地址+低12位0是所对应物理页的地址c
4 计算该虚拟地址对应的物理地址:c + 虚拟地址最低12位
是这样的吗?
实验代码://和老师上课给的代码相同,只是把虚拟地址改成了60010020
int main()
{
char buf[100] = "Hello world";
VirtualAlloc( (void *)0x60010020, 0x3000, MEM_RESERVE, PAGE_READWRITE ); //保留三页
VirtualAlloc( (void *)0x60010020, 0x2000, MEM_COMMIT, PAGE_READWRITE ); //提交两页
printf( "Accessing memory...\n" );
getchar();
memcpy( (void *)0x60010020, buf, 100 );
printf( "Releasing memory...\n");
getchar();
VirtualFree( (void *)0x60010020, 0, MEM_RELEASE );
printf( "Exiting memory...\n" );
getchar();
return 0;
}
1 查寄存器CR3中的值
kd> r cr3
cr3=0e238000
2 计算PDE的物理地址:0e238000 + 00000600= 0e238600
取出该地址处的PDE
kd> !dd 0e238600
# e238600 0dfc9867 00000000 00000000 00000000
# e238610 00000000 00000000 00000000 00000000
# e238620 00000000 00000000 00000000 00000000
# e238630 00000000 00000000 00000000 00000000
# e238640 00000000 00000000 00000000 00000000
# e238650 00000000 00000000 00000000 00000000
# e238660 00000000 00000000 00000000 00000000
# e238670 00000000 00000000 00000000 00000000
3计算PTE的物理地址:0dfc9000 + 00000040 = 0dfc9040
取出该地址处的PTE
kd> !dd 0dfc9040
# dfc9040 0dece867 00000080 00000080 00000000
# dfc9050 00000000 00000000 00000000 00000000
# dfc9060 00000000 00000000 00000000 00000000
# dfc9070 00000000 00000000 00000000 00000000
# dfc9080 00000000 00000000 00000000 00000000
# dfc9090 00000000 00000000 00000000 00000000
# dfc90a0 00000000 00000000 00000000 00000000
# dfc90b0 00000000 00000000 00000000 00000000
4 计算虚拟地址对应的物理地址:0dece000 + 00000020 = 0dece020
取出该物理地址处的数据:
kd> !db 0dece020
# dece020 48 65 6c 6c 6f 20 77 6f-72 6c 64 00 00 00 00 00 Hello world.....
# dece030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
# dece040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
# dece050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
# dece060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
# dece070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
# dece080 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
# dece090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
实验结果表明:虚拟地址0x60010020对应的物理地址为:0dece020,并不需要用到PDE,PTE的虚拟地址,上面的计算方法是正确的
二 通过基址c0300000和c0000000计算出的PDE和PTE的虚拟地址有什么用?
cpu在转换地址的过程中,并不需要页表,页目录的虚拟地址,那为什么还需要计算PDE,PTE的虚拟地址呢?是因为在分页标志设置后,cpu把指令中的虚拟地址转换成物理地址,程序中只能使用虚拟地址,因此要把页目录和页表映射到虚拟地址空间中,页表被映射到了从0xC0000000到0xC03FFFFF的4M地址空间,页目录被映射到了0xC0300000开始处的4K地址空间
因此PDE的虚拟地址为: c0300000 + 00000600 = c0300600
取出该虚拟地址处的PDE,可以看到和上面用PDE的物理地址取出来的结果相同
kd> dd c0300600
c0300600 0dfc9867 00000000 00000000 00000000
c0300610 00000000 00000000 00000000 00000000
c0300620 00000000 00000000 00000000 00000000
c0300630 00000000 00000000 00000000 00000000
c0300640 00000000 00000000 00000000 00000000
c0300650 00000000 00000000 00000000 00000000
c0300660 00000000 00000000 00000000 00000000
c0300670 00000000 00000000 00000000 00000000
PTE的虚拟地址为: c0000000 + 00180040 = c0180040
取出该虚拟地址处的PTE,和上面用PTE的物理地址取出来的结果相同
kd> dd c0180040
c0180040 0dece867 00000080 00000080 00000000
c0180050 00000000 00000000 00000000 00000000
c0180060 00000000 00000000 00000000 00000000
c0180070 00000000 00000000 00000000 00000000
c0180080 00000000 00000000 00000000 00000000
c0180090 00000000 00000000 00000000 00000000
c01800a0 00000000 00000000 00000000 00000000
c01800b0 00000000 00000000 00000000 00000000
上传的附件: