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 記憶體管理核心原理:從核心空間 (頁、區、Slab、vmalloc) 到使用者空間 (VMA、mm_struct、fork 複製) 完整圖解

編輯:Linux 教學

一、核心空間記憶體管理

1.1 頁 : 最小管理單位

struct page {
    page_flags_t flags;      // 頁狀態位圖 (髒、鎖定、複合頁等)
    atomic_t _count;         // 參考計數 (-1 表示空閒)
    atomic_t _mapcount;      // 頁表映射計數
    unsigned long private;   // 私有資料指標
    struct address_space *mapping; // 歸屬 address_space (檔案頁)
    pgoff_t index;           // 在 address_space 中的索引 (檔案偏移)
    struct list_head lru;    // LRU 鏈表掛載點
    void *virtual;           // 核心虛擬位址 (高端記憶體為 NULL)
};
  • 4KB 頁框 → 4GB 實體記憶體 ≈ 1M 個 struct page → 佔 40MB 核心記憶體 (可接受)。
  • page_address(page) 取得核心邏輯位址;高端記憶體需 kmap() 臨時映射。

1.2 區 : 依物理位址可達性分區

區域物理位址範圍 (x86_32)用途
ZONE_DMA< 16 MBISA 設備 DMA 必須使用
ZONE_NORMAL16 ~ 896 MB核心直接永久映射區 (低端記憶體)
ZONE_HIGHMEM> 896 MB高端記憶體,需動態映射 (kmap/vmap) 才能由核心存取

x86_64 無 HIGHMEM,全部為 ZONE_NORMAL (直接映射)。

1.3 頁級分配器 (Buddy System) — 以 2^n 頁為單位

函式行為返回值
alloc_pages(gfp_mask, order)分配 2^order 頁首頁 struct page*
alloc_page(gfp_mask)分配單頁struct page*
__get_free_pages(gfp_mask, order)分配 2^order 頁核心邏輯位址
get_zeroed_page(gfp_mask)分配單頁並清零核心邏輯位址

對應釋放:__free_pages, free_pages, free_page。

GFP 旗標:GFP_KERNEL (可睡眠、一般核心分配)、GFP_ATOMIC (不可睡眠、中斷上下文)、GFP_USER (用戶空間分配)、GFP_HIGHUSER (高端記憶體)、__GFP_ZERO (清零)、__GFP_DMA (ZONE_DMA)。

1.4 位元組級分配器

函式連續性最大尺寸釋放適用場景
kmalloc(size, flags)物理連續128KB (32 頁)kfree高頻小物件、DMA 緩衝區
kzalloc(size, flags)物理連續 + 清零同上kfree安全初始化
vmalloc(size)虛擬連續 (物理離散)理論無上限 (受限 vmalloc 區)vfree大型緩衝區、模組載入、核心棧
效能:kmalloc 走 Buddy + Slab,快;vmalloc 需建立頁表映射,TLB 刷新開銷大,分配慢但易得大塊記憶體。

1.5 Slab 分配器 : 物件快取層

  • 針對頻繁分配/釋放的固定大小結構體 (如 task_struct, inode, dentry)。
  • 每種物件一個 kmem_cache,含多個 slab (一組連續頁框),Slab 內劃分為物件。
  • Per-CPU 快取減少鎖競爭與快取行彈跳。
  • API:kmem_cache_create, kmem_cache_alloc, kmem_cache_free, kmem_cache_destroy。

1.6 核心棧 : 單頁模式

  • 配置選項 CONFIG_THREAD_STACK_PAGES=1 (4KB) 或 2 (8KB)。
  • 優點:減少記憶體佔用、緩解碎片化分配壓力、中斷處理有獨立棧。
  • 限制:函式區域變數總和不可超過數百位元組,避免棧溢位。

1.7 高端記憶體映射

  • kmap(page) / kunmap(page):永久映射 (全域鎖,數量有限)。
  • kmap_atomic(page) / kunmap_atomic():臨時映射 (Per-CPU 槽位,無鎖,中斷上下文可用)。

1.8 Per-CPU 變數

  • alloc_percpu(type) / free_percpu(ptr):每 CPU 一份實例。
  • get_cpu_var(var) / put_cpu_var(var):存取並禁止/啟用搶佔。
  • 優勢:零鎖存取、消除快取行彈跳 (Cache Line Bouncing)。

二、使用者空間記憶體管理

2.1 進程位址空間 = VMA (Virtual Memory Area) 集合

每個 VMA (struct vm_area_struct) 描述一段連續虛擬位址區間,屬性含:

  • 起始/結束位址 (vm_start, vm_end)
  • 權限 (vm_flags : READ/WRITE/EXEC/SHARED/MAYSHARE...)
  • 對應檔案/物件 (vm_file, vm_pgoff)
  • 操作函式表 (vm_ops : open/close/fault/mmap...)

典型 VMA 類型:

  • 程式碼段 (text, RX)、資料段 (data, RW)、BSS (RW, 零頁映射)
  • 使用者棧 (增長方向向下、守衛頁)
  • 共享函式庫 (libc, ld.so 等) 代碼/資料/BSS
  • 記憶體映射檔案 (mmap)
  • 共享記憶體 (shmget/mmap MAP_SHARED)
  • 匿名映射 (malloc/mmap MAP_ANONYMOUS)

2.2 mm_struct : 進程記憶體描述符

struct mm_struct {
    struct vm_area_struct *mmap;      // VMA 單向鏈表 (遍歷用)
    struct rb_root mm_rb;             // VMA 紅黑樹 (查找用)
    atomic_t mm_users;                // 使用者空間執行緒計數
    atomic_t mm_count;                // 核心引用計數
    struct list_head mmlist;          // 全域 mm_struct 雙向鏈表
    // ... pgd, start_code, end_code, start_data, end_data, start_brk, brk, start_stack, arg_start, arg_end, env_start, env_end
};
  • task_struct->mm 指向進程的 mm_struct;核心執行緒 mm = NULL,借用前一進程的 active_mm 存取核心空間映射。

2.3 fork() 複製語意

  • 預設 fork():copy_mm() → 複製 mm_struct、頁表、VMA (Copy-on-Write, COW);物理頁框共享,寫入時才分離。
  • clone(CLONE_VM):共享 mm_struct (執行緒模型)。
  • vfork():共享 mm_struct 且父進程阻塞,子進程 exec 或 exit 才喚醒父進程 (極度危險,僅用於 exec 前)。

2.4 記憶體回收與 OOM Killer

  • 匿名頁回收 → 寫入 swap (若有) → 釋放頁框。
  • 檔案映射頁回收 → 直接丟棄 (可從磁碟重讀)。
  • 記憶體極度不足觸發 oom_killer,依 oom_score 選擇犧牲進程 (可透過 /proc//oom_score_adj 調整)。
Copyright © Windows教程網 All Rights Reserved