免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5816 | 回复: 8
打印 上一主题 下一主题

好奇想看一下映射内核地址空间的页表,写了个内核模块 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-02-02 15:38 |只看该作者 |倒序浏览
unsigned long *pgd = (unsigned long*)(current->mm->pgd);
printk( KERN_DEBUG "pgd=0x%lx\n", pgd);
for(i=768;i<1024;++i){
  printk( KERN_DEBUG "pgd[%d]=0x%lx\n", i, pgd[i]);
}

结果 pgd=0xdd53c000  但是pgd[768..1023]打印出来的全是零。不知道怎么解释?按理它们应该指向一系列的页表才对啊!

论坛徽章:
2
2015亚冠之莱赫维亚
日期:2015-09-14 11:19:42操作系统版块每日发帖之星
日期:2015-11-05 06:20:00
2 [报告]
发表于 2010-02-02 22:52 |只看该作者
mark

论坛徽章:
0
3 [报告]
发表于 2010-02-03 00:02 |只看该作者
pgd里面存放的是物理地址吧,要打印的话,需要对应的线性地址

论坛徽章:
0
4 [报告]
发表于 2010-02-03 04:16 |只看该作者
本帖最后由 accessory 于 2010-02-03 04:18 编辑

LS说得对,PGD里得内容是物理地址,不能直接打印的。LZ代码里的另外一个错误是下面这句:
unsigned long *pgd = (unsigned long*)(current->mm->pgd);

这里current->mm->pgd 是一个pgd_t 类型,在X86-32下是这样定义的:
typedef struct { unsigned long pgd; } pgd_t;
所以不能直接转换成unsigned long

下面是我写的一段小代码。它用了另外一个思路。就是给定内核段的地址,把这个地址对应的pgd index, pgd 项的内容打印出来。代码如下:
  1.         pgd_t *pgdp = (current->mm->pgd);
  2.         unsigned long addr = 0xc0000000, tmp, *pp;

  3.         printk( KERN_DEBUG "pgd=0x%lx\n", pgdp->pgd);
  4.         for(tmp=addr;tmp<0xc1000000;tmp+=0x400000){
  5.                 printk( KERN_DEBUG "pgd_index(0x%lx)=%d\n", tmp, pgd_index(tmp) );
  6.                 pp = pgd_offset_k(tmp);
  7.                 printk("conten of pdg is 0x%lx\n", *pp);       
  8.         }
复制代码
得到的结果如下:
Feb  2 15:01:48 localhost kernel: [ 5735.958715] pgd=0x3128067
Feb  2 15:01:48 localhost kernel: [ 5735.958762] pgd_index(0xc0000000)=768
Feb  2 15:01:48 localhost kernel: [ 5735.958794] conten of pdg is 0x1e3
Feb  2 15:01:48 localhost kernel: [ 5735.958832] pgd_index(0xc0400000)=769
Feb  2 15:01:48 localhost kernel: [ 5735.958856] conten of pdg is 0x4001e3
Feb  2 15:01:48 localhost kernel: [ 5735.958881] pgd_index(0xc0800000)=770
Feb  2 15:01:48 localhost kernel: [ 5735.958904] conten of pdg is 0x8001e3
Feb  2 15:01:48 localhost kernel: [ 5735.958930] pgd_index(0xc0c00000)=771
Feb  2 15:01:48 localhost kernel: [ 5735.958953] conten of pdg is 0xc001e3

经过多次INSMOD, RMMOD实验,发现第一个pgd输出会变。后面的全都不变。证实了所有进程的内核段都是一样的。

以上的测试环境:QEMU VM, CENTOS 5.3 LINUX 2.6.18 X86-32.

LZ可以参考上面的思路把后面的PTE也打印出来。

另外,可以参考下面这个帖子的第九楼:
http://linux.chinaunix.net/bbs/viewthread.php?tid=1124661

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
5 [报告]
发表于 2011-09-22 11:38 |只看该作者
LS这里用 pgd_offset_k得到在pgd相应项的线性地址,这个宏貌似是得到master kernel page global directory的,而不是每个进程的。

论坛徽章:
0
6 [报告]
发表于 2011-09-22 13:38 |只看该作者
本帖最后由 vonnyfly 于 2011-09-22 13:44 编辑

回复 4# accessory

第一个变正常的,每个进程的pgd位置肯定不同。而后面的不变也很正常,你给定内核虚拟地址,pgd_index取最高10位,而pgd_offset_k取的是init_mm.pgd+pgd_index的偏移量,肯定也不变的啊。所以这不能得出结论,所有的进程共享内核页表。应该在for循环里面,通过模拟MMU的页表转换打印对应的物理地址。

论坛徽章:
0
7 [报告]
发表于 2011-09-26 10:50 |只看该作者
呀,我以前还发过这个帖子啊。几乎完全忘记了。。。= =

论坛徽章:
0
8 [报告]
发表于 2011-09-26 20:31 |只看该作者
应该去打印init_mm中的pgd项,那个才是内核使用的页目录表。其他pgd中为0也是正常,这样会产生缺页异常,结果就是将init_mm中的pgd中对应的项拷贝到当前进程的pgd中相应的项。

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2011-10-04 13:19 |只看该作者
如何证明?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP