首先,根据一个虚拟地址是可以得到物理地址的,这个内核模块是可以做到的。
大概就以下这几步:
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;
在运行这个代码的时候,要导出一些内核函数。