Linux 記憶體管理是作業系統核心中最複雜、最關鍵的子系統之一。本文系統闡述 虛擬記憶體抽象、x86 分頁/分段轉換流程、多級頁表結構、TLB (Translation Lookaside Buffer) 機制、核心記憶體分配器 (Buddy System + Slab/SLUB) 五大支柱,並對照原始碼關鍵路徑 (mm/) 提供圖解與實驗驗證方法。
0x400000),載入器只需建立映射,無需重定位。
虛擬地址 (48 位 canonical) 分解:
| PML4 index (9 bits) | PDPT index (9 bits) | PD index (9 bits) | PT index (9 bits) | Page Offset (12 bits) |
| bits 47-39 | bits 38-30 | bits 29-21 | bits 20-12 | bits 11-0 |
CR3 (頁表基址暫存器) → PML4 Table (512 entries)
→ PDPT (Page Directory Pointer Table)
→ PD (Page Directory) → 2MB 大頁 (若 PS=1) 或
→ PT (Page Table) → 4KB 頁框
每級頁表項 (PTE) 64 位,關鍵旗標:P (Present)、R/W、U/S (User/Supervisor)、PWT/PCD (Write-Through/Cache Disable)、A (Accessed)、D (Dirty)、PS (Page Size)、G (Global)、NX (No-eXecute)。
// include/linux/pgtable.h
typedef struct { unsigned long pgd; } pgd_t; // Page Global Directory
typedef struct { unsigned long p4d; } p4d_t; // Page 4th Directory (5級頁表預留)
typedef struct { unsigned long pud; } pud_t; // Page Upper Directory
typedef struct { unsigned long pmd; } pmd_t; // Page Middle Directory
typedef struct { unsigned long pte; } pte_t; // Page Table Entry
宏 pgd_offset(mm, addr)、p4d_offset()、pud_offset()、pmd_offset()、pte_offset_map() 串聯查找路徑。
| 特性 | 說明 |
|---|---|
| 位置 | CPU 核心內部 (L1/L2 TLB 分離指令/資料) |
| 容量 | 典型 64~1536 entries (視微架構) |
| 關聯度 | 全相聯 / 集合相聯 |
| 失效機制 | invlpg (單頁)、mov cr3 (全域)、PCID (Process Context ID) 標記保留 |
| 大頁優勢 | 2MB/1GB 大頁僅佔 1 TLB entry,覆蓋更大地址範圍,減少 TLB Miss |
驗證 TLB 行為:perf stat -e dTLB-load-misses,dTLB-store-misses ./workload
mm/page_alloc.c)ZONE_DMA/ZONE_DMA32/ZONE_NORMAL/ZONE_HIGHMEM/ZONE_MOVABLEalloc_pages(gfp_mask, order)、__get_free_pages()、free_pages()mm/slub.c,現代預設)kmem_cache (如 kmalloc-64, task_struct, inode_cache)kmalloc(size, gfp)/kfree(ptr)、kmem_cache_alloc(cache, gfp)/kmem_cache_free(cache, obj)| 旗標 | 含義 | 典型用途 |
|---|---|---|
GFP_KERNEL | 可睡眠、可回收、可觸發回收 | 進程上下文、大多數驅動 |
GFP_ATOMIC | 不可睡眠、不回收、高優先級 | 中斷上下文、Spinlock 持有期間 |
GFP_DMA | 限制 ZONE_DMA (ISA 相容) | 舊式裝置 DMA |
__GFP_HIGHMEM | 允許 HIGHMEM 區域 | 大量資料緩衝 |
__GFP_RECLAIM/__GFP_NORECLAIM | 控制是否觸發直接回收 | 延遲敏感路徑 |
# 1. 查看進程虛擬記憶體佈局
cat /proc//maps
pmap -x
# 2. 系統級記憶體統計
cat /proc/meminfo
cat /proc/buddyinfo # Buddy 空閒區塊分佈
cat /proc/slabinfo # SLUB 快取統計 (需 root)
slabtop -o # 互動式 SLUB 監控
# 3. 核心記憶體洩漏偵測
echo 1 > /proc/sys/vm/drop_caches # 清理 page cache
kmemleak 巡檢 (CONFIG_DEBUG_KMEMLEAK)
# 4. TLB Miss 分析
perf stat -e dTLB-load-misses,iTLB-load-misses ./app
# 5. 頁表走查 (需 CONFIG_DEBUG_PAGEALLOC)
echo 1 > /proc/sys/vm/debug_pagealloc
mmap(MAP_HUGETLB) 或 hugetlbfs。/proc/buddyinfo 高階區塊歸零 → echo 1 > /proc/sys/vm/compact_memory 主動整理 或 sysctl vm.extfrag_threshold。slub_nomerge、slub_debug 或自定義 kmem_cache。vm.swappiness 過高、vm.min_free_kbytes 過低 → 調整回收水位。深入理解 Linux 記憶體管理的分層抽象、硬體協作機制 (TLB/頁表) 與核心分配器演算法,是進行核心開發、效能調優、記憶體洩漏偵測、容器資源隔離 (cgroup v2 memory.max) 的必修內功。