关于PDE/PTE
以前写的一篇关于OS的文章,希望以后还能抽时间不断地阅读内核代码,把一些感兴趣的问题搞清楚 :D
上节课老师讲了关于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
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:stonefish 来源: stonefish9
- 标签: PDE PTE
- 发布时间:2010-07-23 00:20:48
- [2527] 代理的加密部分
- [1327] 创业笔记 | 从0到1开公司是什么体验
- [646] vimgtd-在vim(gvim)中实现GT
- [570] 查找第K小的元素
- [69] Oracle MTS模式下 进程地址与会话信
- [64] Go Reflect 性能
- [62] 【社会化设计】自我(self)部分――欢迎区
- [61] 如何拿下简短的域名
- [59] 图书馆的世界纪录
- [57] android 开发入门