理解 Linux 記憶體尋址需區分三種地址空間,掌握 MMU(記憶體管理單元)的分段+分頁兩級轉換流程,以及為何現代核心採用四級頁表支援 64 位架構。
| 地址類型 | 定義 | 範圍(32位) | 備註 |
|---|---|---|---|
| 物理地址 | 記憶體總線上的真實地址,直接驅動 DRAM 選列/行 | 0 ~ 4GB-1 | 由硬體決定,核心通過 __pa()/__va() 轉換 |
| 虛擬地址 | 進程看到的地址,格式「段選擇子:偏移量」 | 0 ~ 4GB-1 | 用戶態指針、函數參數均為虛擬地址 |
| 線性地址 | 分段轉換後的中間地址,平坦、連續、無段界限 | 0 ~ 4GB-1 | Linux 將所有段基址設 0,限長 4GB,虛擬≈線性 |
32 位 4GB 空間若用單級頁表:1M 頁 × 4 字節 = 4MB 連續內存,分配困難且浪費(稀疏地址空間)。兩級頁表將頁表再分頁:PGD(1K 項)指向 PTE 頁表(每 1K 項映射 4MB),僅為已映射區域分配 PTE 頁,極大節省內核內存。
x86_64/ARM64 採用 48 位虛擬地址(256TB),四級結構:
PGD (Page Global Directory) 512 項, 每項覆蓋 512GB
PUD (Page Upper Directory) 512 項, 每項覆蓋 1GB
PMD (Page Middle Directory) 512 項, 每項覆蓋 2MB (大頁) 或指向 PTE
PTE (Page Table Entry) 512 項, 每項映射 4KB 頁框
Linux 定義 pgd_t、pud_t、pmd_t、pte_t 統一類型,通過 pgd_offset()→pud_offset()→pmd_offset()→pte_offset_map() 遍歷。支援 大頁(HugeTLB,2MB/1GB) 直接由 PMD/PUD 映射,減少 TLB 缺失、提升數據庫/高性能計算場景性能。
CPU 內建 TLB(Translation Lookaside Buffer)快取近期頁表項。x86 典型 64 項 L1 TLB + 512 項 L2 TLB,覆蓋 128KB~2MB 內存。核心提供 flush_tlb_all()、flush_tlb_page()、invlpg 指令管理 TLB 一致性。PGE(全局頁標誌)防止內核映射被用戶態切換刷新。