虛擬地址轉換為物理地址【轉】


轉自:https://blog.csdn.net/shuningzhang/article/details/38090621

應用程序只能提供一個虛擬地址,也可以通過如下方法獲取物理地址,當然得調用驅動。

Linux采用頁表的概念來管理虛擬空間,內核在處理虛擬地址時都必須將其轉換為物理地址,然后處理器才能夠訪問。虛擬地址可以通過Linux的頁表操作宏逐層查找到物理地址,簡單來說需要將虛擬地址分段,每段地址都作為索引指向頁表,最后一級頁表指向物理地址。
 Linux在2.6.11以后版本為了兼容各種處理器,采用四級頁表結構:
 PGD:Page Global Directory,頁全局目錄,是頂級頁表。
 PUD:Page Upper Directory,頁上級目錄,是第二級頁表
 PMD:Page Middle Derectory,頁中間目錄,是第三級頁表。
 PTE:Page Table Entry,頁面表,最后一級頁表,指向物理頁面。
 可以通過數據結構mm_struct訪問PGD找到物理頁面,如圖4-8,根據頁表尋找物理地址的流程見4-9。
 
圖  Linux采用的4級頁面
 

 簡化的轉換代碼如下:
 static int vir2phy(unsigned long va) 
 {     
  struct task_struct *pcb_tmp;     
  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; 
 }

pgd_offset(mm, addr) 接收內存描述符地址mm和線性地址addr作為參數。這個宏產生地址addr在頁全局目錄中相應表項的線性地址;
通過內存描述符mm內的一個指針可以找到這個頁全局目錄。

pud_offset(pgd, addr) 參數為指向頁全局目錄項的指針pgd和線性地址addr。這個宏產生頁上級目錄中目錄項addr對應的線性地址。在兩級或三級分頁系統中,該宏產生pgd,即一個頁全局目錄項的地址。

pmd_offset(pud, addr) 接收指向頁上級目錄項的指針pud和線性地址addr作為參數。這個宏產生目錄項addr在頁中間目錄中的偏移地址。在兩級或三級分頁系統中,它產生pud,即頁全局目錄項的地址。

pte_offset_kernel(dir, addr) 線性地址addr在頁中間目錄dir中有一個對應的項,該宏就產生這個對應項,即頁表的線性地址。另外,該宏只在主內核頁表上使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM