Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 記憶體管理核心原理深度解析:虛擬地址、頁表、TLB 與 Slab 分配器

編輯:Linux 教學

Linux 記憶體管理是作業系統核心中最複雜、最關鍵的子系統之一。本文系統闡述 虛擬記憶體抽象、x86 分頁/分段轉換流程、多級頁表結構、TLB (Translation Lookaside Buffer) 機制、核心記憶體分配器 (Buddy System + Slab/SLUB) 五大支柱,並對照原始碼關鍵路徑 (mm/) 提供圖解與實驗驗證方法。

一、虛擬記憶體:為什麼需要這層抽象?

  • 地址空間隔離:每個進程擁有獨立 4GB (32 位) / 256 TB (48 位) 虛擬地址空間,互不干擾。
  • 記憶體超額使用:配合換頁 (Swap) 與檔案映射 (mmap),物理記憶體可小於虛擬記憶體總和。
  • 共享與保護:共享程式碼段、共享庫、Copy-on-Write (COW)、唯讀/執行/寫入權限位。
  • 簡化連結載入:連結器固定虛擬地址 (如 0x400000),載入器只需建立映射,無需重定位。

二、x86_64 四級頁表轉換流程 (CR3 → PML4 → PDPT → PD → PT → Page)


虛擬地址 (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)。

三、Linux 核心對頁表的抽象:pgd_t / p4d_t / pud_t / pmd_t / pte_t


// 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() 串聯查找路徑。

四、TLB:CPU 內建的頁表快取

特性說明
位置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

五、核心記憶體分配器:Buddy System + SLUB

1. Buddy System (頁框級分配器 mm/page_alloc.c)

  • 以 2 的冪次區塊 (Order 0~10/11) 管理實體頁框
  • 分配:尋找最小滿足 order 的空閒區塊,不足則分裂 (split)
  • 釋放:嘗試與相鄰 buddy 合併 (coalesce) 升級 order
  • 區域 (Zone) 分類:ZONE_DMA/ZONE_DMA32/ZONE_NORMAL/ZONE_HIGHMEM/ZONE_MOVABLE
  • 介面:alloc_pages(gfp_mask, order)、__get_free_pages()、free_pages()

2. SLUB (物件級分配器 mm/slub.c,現代預設)

  • Cache:每種物件大小建立一個 kmem_cache (如 kmalloc-64, task_struct, inode_cache)
  • Slab:由一或多個連續頁框組成,切割成固定大小物件
  • Per-CPU Partial Slab:每 CPU 維護部分滿 Slab 減少鎖競爭
  • Random Freelist / Redzone / Poison:偵測緩衝區溢位、Use-after-free
  • 介面:kmalloc(size, gfp)/kfree(ptr)、kmem_cache_alloc(cache, gfp)/kmem_cache_free(cache, obj)

3. GFP 旗標關鍵組合

旗標含義典型用途
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

七、常見效能問題與調優方向

  1. TLB Thrashing:大量小頁映射 → 改用 HugeTLB (2MB/1GB) mmap(MAP_HUGETLB) 或 hugetlbfs。
  2. Buddy 碎片化:/proc/buddyinfo 高階區塊歸零 → echo 1 > /proc/sys/vm/compact_memory 主動整理 或 sysctl vm.extfrag_threshold。
  3. SLUB 鎖競爭:高併發分配同一大小物件 → 調整 slub_nomerge、slub_debug 或自定義 kmem_cache。
  4. Swap Storm:vm.swappiness 過高、vm.min_free_kbytes 過低 → 調整回收水位。

深入理解 Linux 記憶體管理的分層抽象、硬體協作機制 (TLB/頁表) 與核心分配器演算法,是進行核心開發、效能調優、記憶體洩漏偵測、容器資源隔離 (cgroup v2 memory.max) 的必修內功。

Copyright © Windows教程網 All Rights Reserved