+ -
当前位置:首页 → 问答吧 → 内核虚拟地址转换为物理地址(模拟__pa)

内核虚拟地址转换为物理地址(模拟__pa)

时间:2011-09-15

来源:互联网

C/C++ code
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/pgtable.h>
#include <asm/page.h>
static int vir2phy(unsigned long va)
{
struct task_struct *pcb_tmp;
pgd_t* pgd_tmp;
pmd_t* pmd_tmp;
pud_t * pud_tmp;
pte_t * pte_tmp;
int pa;
pcb_tmp = current;
pgd_tmp = pgd_offset(pcb_tmp->mm,va);
pud_tmp = pud_offset(pgd_tmp,va);
pmd_tmp = pmd_offset(pud_tmp,va);
pte_tmp = pte_offset_kernel(pmd_tmp,va);
pa = (pte_val(*pte_tmp) & PAGE_MASK) |(va & ~PAGE_MASK);
return pa;
}

static int hello_init(void)
{
int* vaddr=kmalloc(30,GFP_KERNEL);
printk("the phy address of 0x%x is:0x%x\n",vaddr,vir2phy(vaddr));
return 0;
}

static void hello_exit(void)
{
}

module_init(hello_init);
module_exit(hello_exit);


打印如下:
the phy address of 0xc5382ee0 is:0xa787ee0

kmalloc分配的地址应该是在前896M的,与物理内存的前896M存在3g的偏移。
内核虚拟地址和物理地址不是存在一个3g的偏移的嘛?0xc5382ee0在3g~3g+896M之间,它的物理地址应该是0x5382ee0才对呀,怎么打印出来的是0xa787ee0呢?
虽然函数vir2phy用的是当前进程的页目录表,但是768-1024之间的是内核空间的页目录表,而0xc5382ee0的页目录表索引为1100010100(10进制为788,在内核空间的页目录表中),为什么和__pa的结果不一样呢?

作者: yjcqbbs   发布时间: 2011-09-15

赞学习精神,思路没错,根据进程的页表也应该能找到kmalloc的物理地址,建议多试几个地址,看有没有规律。
我估计是那几个转换没弄对

作者: cdbdyx   发布时间: 2011-09-16

C/C++ code

    #include <asm/io.h>
    phys_addr = virt_to_phys(virt_addr);
    virt_addr = phys_to_virt(phys_addr); bus_addr = virt_to_bus(virt_addr); virt_addr = bus_to_virt(bus_addr);

作者: wenxy1   发布时间: 2011-09-16