写自己的内核模块——获取一个进程的物理地址

来源:互联网 发布:高通kryo 知乎 编辑:程序博客网 时间:2024/05/17 23:22

首先,根据一个虚拟地址是可以得到物理地址的,这个内核模块是可以做到的。
大概就以下这几步:
1、得到当前进程的task_struct结构体(类似于current宏的实现)
2、得到进程的mm_struct结构体
3、搞一个虚拟地址(一个变量的地址或者一个函数的地址)
4、先得到pgd,然后根据pgd找到pud,根据pud找到pte,当当当当,你得到了该变量(或者函数)所在页面的页表表项地址,意味着你得到了偏移量。
5、现在要做的就是根据页表的到页面的物理地址,和偏移量相加。done,物理地址得到。
实现代码如下:

 int i = 1;              //得到了一个虚拟地址unsigned long addr = (unsigned long)(&i);unsigned long real_addr;unsigned long *pte_addr;//得到个当前进程的task_struct结构体struct task_struct *curr= get_current();        //得到当前进程的mm_struct结构体struct mm_struct *mm = curr->mm;struct pgd_t  *pgd = pgd_offset(mm,addr);if(!pgd){     printk("pgd error!\n");     return 0;}struct pud_t *pud = pud_offset(pgd,addr);struct pmd_t *pmd = pmd_offset(pud,addr);if(!pmd){    printk("pmd error!\n");    return 0;     }                                                       //得到页表项地址    unsigned long pte = pte_offset(pmd,addr);           if(!pte){     printk("pte error\n");     return 0;}//得到页内偏移量(线性地址的后12位)real_addr = addr&0x00000fff;        pte_addr = pte;//页表表项内容后20位填充的是页框起始地址real_addr += (*pte_addr)&0x000fffff;               printk("\t虚拟地址为%ld\n",addr);printk("\t物理地址为%ld\n",real_addr);return 0;

在运行这个代码的时候,要导出一些内核函数。

0 0