最近做opengl模拟器的时候,需要从用户虚拟地址得到实际的物理地址,在网上找到一个不错的参考(http://www.eefocus.com/html/09-05/71993s.shtml,稍微修改了一下(用current替代了find_task_by_pid.

  1. #include <linux/sched.h> 
  2. #include <linux/mm.h> 
  3. #include <asm/pgtable.h> 
  4. #include <asm/page.h> 
  5.  
  6. static int v2p(unsigned long va) 
  7.     unsigned long pa = 0; 
  8.     struct task_struct *pcb_tmp; 
  9.     pgd_t *pgd_tmp = NULL; 
  10.     pud_t *pud_tmp = NULL; 
  11.     pmd_t *pmd_tmp = NULL; 
  12.     pte_t *pte_tmp = NULL; 
  13.  
  14.     printk(KERN_INFO"PAGE_OFFSET = 0x%lx\n",PAGE_OFFSET); 
  15.     printk(KERN_INFO"PGDIR_SHIFT = %d\n",PGDIR_SHIFT); 
  16.     printk(KERN_INFO"PUD_SHIFT = %d\n",PUD_SHIFT); 
  17.     printk(KERN_INFO"PMD_SHIFT = %d\n",PMD_SHIFT); 
  18.     printk(KERN_INFO"PAGE_SHIFT = %d\n",PAGE_SHIFT); 
  19.  
  20.     printk(KERN_INFO"PTRS_PER_PGD = %d\n",PTRS_PER_PGD); 
  21.     printk(KERN_INFO"PTRS_PER_PUD = %d\n",PTRS_PER_PUD); 
  22.     printk(KERN_INFO"PTRS_PER_PMD = %d\n",PTRS_PER_PMD); 
  23.     printk(KERN_INFO"PTRS_PER_PTE = %d\n",PTRS_PER_PTE); 
  24.  
  25.     printk(KERN_INFO"PAGE_MASK = 0x%lx\n",PAGE_MASK); 
  26.  
  27.     pcb_tmp = current; 
  28.     printk(KERN_INFO"pgd = 0x%p\n",pcb_tmp->mm->pgd); 
  29.     if(!find_vma(pcb_tmp->mm,va)){ 
  30.                     printk(KERN_INFO"virt_addr 0x%lx not available.\n",va); 
  31.                     return 0; 
  32.     } 
  33.     pgd_tmp = pgd_offset(pcb_tmp->mm,va); 
  34.     printk(KERN_INFO"pgd_tmp = 0x%p\n",pgd_tmp); 
  35.     printk(KERN_INFO"pgd_val(*pgd_tmp) = 0x%lx\n",pgd_val(*pgd_tmp)); 
  36.     if(pgd_none(*pgd_tmp)){ 
  37.                     printk(KERN_INFO"Not mapped in pgd.\n");                 
  38.                     return 0; 
  39.     } 
  40.     pud_tmp = pud_offset(pgd_tmp,va); 
  41.     printk(KERN_INFO"pud_tmp = 0x%p\n",pud_tmp); 
  42.     printk(KERN_INFO"pud_val(*pud_tmp) = 0x%lx\n",pud_val(*pud_tmp)); 
  43.     if(pud_none(*pud_tmp)){ 
  44.                     printk(KERN_INFO"Not mapped in pud.\n"); 
  45.                     return 0; 
  46.     } 
  47.     pmd_tmp = pmd_offset(pud_tmp,va); 
  48.     printk(KERN_INFO"pmd_tmp = 0x%p\n",pmd_tmp); 
  49.     printk(KERN_INFO"pmd_val(*pmd_tmp) = 0x%lx\n",pmd_val(*pmd_tmp)); 
  50.     if(pmd_none(*pmd_tmp)){ 
  51.                     printk(KERN_INFO"Not mapped in pmd.\n"); 
  52.                     return 0; 
  53.     } 
  54.  
  55.     pte_tmp = pte_offset_kernel(pmd_tmp,va); 
  56.  
  57.     printk(KERN_INFO"pte_tmp = 0x%p\n",pte_tmp); 
  58.     printk(KERN_INFO"pte_val(*pte_tmp) = 0x%lx\n",pte_val(*pte_tmp)); 
  59.     if(pte_none(*pte_tmp)){ 
  60.                     printk(KERN_INFO"Not mapped in pte.\n"); 
  61.                     return 0; 
  62.     } 
  63.     if(!pte_present(*pte_tmp)){ 
  64.                     printk(KERN_INFO"pte not in RAM.\n"); 
  65.                     return 0; 
  66.     } 
  67.     pa = (pte_val(*pte_tmp) & PAGE_MASK) |(va & ~PAGE_MASK); 
  68.     printk(KERN_INFO"virt_addr 0x%lx in RAM is 0x%lx .\n",va,pa); 
  69.     printk(KERN_INFO"contect in 0x%lx is 0x%lx\n",pa, 
  70.                     *(unsigned long *)((char *)pa + PAGE_OFFSET)); 
  71.                                                                                                      
  72.     return 0;