服务器设置和教程 · 3 8 月, 2025

深入解析 Linux 記憶體管理中的分頁機制

正文:
本文將詳細探討 Linux 核心中的分頁機制,涵蓋記憶體模型、節點與區域劃分、頁面分配策略、核心頁表和頁面交換等核心內容。同時,結合香港伺服器的實際應用場景,分析其在高性能計算中的優化實踐。本教程結構清晰、層次分明,旨在幫助讀者深入理解 Linux 記憶體管理的分頁原理。


一、引言

記憶體管理是作業系統的核心功能之一,確保行程能夠高效利用系統資源,同時維持系統的穩定性和效能。在伺服器等高性能計算環境中,記憶體管理尤為重要,因為這些伺服器通常需要處理大量併發請求、運行多個虛擬機器或容器化應用,並支援高密度的資料中心需求。Linux 作為主流的伺服器作業系統,提供了強大的記憶體管理機制,其中分頁機制是其虛擬記憶體管理的關鍵組成部分。

本文將從以下幾個方面展開討論:

  1. 記憶體模型: 平坦記憶體模型、SMP 和 NUMA 的特性與應用。

  2. 記憶體的層次劃分: 節點、區域和頁面的組織方式。

  3. 頁面分配機制: 夥伴系統和 Slub Allocator 的實作原理。

  4. 核心頁表: 初始化和虛擬到實體位址的映射。

  5. 頁面交換: 被動回收和主動管理的策略。

透過這些內容,讀者將能夠理解 Linux 記憶體管理中的分頁機制,並認識到其在伺服器等高效能環境中的實際應用價值。


二、記憶體模型概述

Linux 支援多種記憶體模型,以適應不同的硬體架構和效能需求。以下是三種主要記憶體模型的簡介:

  • 2.1 平坦記憶體模型 (Flat Memory Model)

    • 描述: 採用連續的實體位址空間,頁面編號與位址之間存在簡單的線性映射。

    • 優點: 結構簡單,適合早期硬體或小型系統。

    • 缺點: 隨著記憶體需求和行程數量的增加,其擴充性受限,無法滿足現代多處理器系統的複雜需求。

    • 應用場景: 適用於資源受限的嵌入式系統或早期電腦。

  • 2.2 對稱多處理模型 (Symmetric Multi-Processing, SMP)

    • 描述: 允許多個處理器平等存取共享主記憶體,由單一作業系統統一排程。

    • 特點: 透過負載平衡最佳化資源利用率;所有處理器共享同一記憶體空間,可能導致存取爭用。

    • 應用場景: 廣泛用於多核伺服器環境中,提升併發處理能力,適合運行多執行緒應用或虛擬化環境。

  • 2.3 非均勻記憶體存取模型 (Non-Uniform Memory Access, NUMA)

    • 描述: 每個 CPU 擁有本地記憶體,存取本地記憶體的延遲低於遠端記憶體;CPU 和記憶體共同構成 NUMA 節點。

    • 特點: 透過最佳化本地記憶體存取,顯著提高效能;但跨節點存取會增加延遲。

    • 應用場景: 在伺服器中,NUMA 模型透過最佳化記憶體分配,顯著提高高效能計算任務的效率,如資料庫處理或分散式計算。

    • 挑戰: 當本地記憶體不足時,跨節點存取需要核心進行智慧的記憶體分配策略。

總結: 在伺服器中,NUMA 模型尤為重要,因為它能夠更好地適應多處理器架構和高性能需求,減少記憶體存取延遲,提升系統吞吐量。


三、記憶體的層次劃分

Linux 將實體記憶體劃分為節點 (Node)區域 (Zone) 和頁面 (Page) 三個層次,以實現高效管理。

  • 3.1 節點 (Node)

    • 描述: 在 NUMA 架構中,記憶體被劃分為多個節點,每個節點對應一個 CPU 及其本地記憶體。

    • 結構: 透過 pglist_data 結構體描述,包含以下關鍵欄位:

      • node_id:節點唯一標識。

      • node_zones:節點內的區域陣列。

      • node_zonelists:備用節點和區域的鏈結串列。

      • node_mem_map:節點的頁面陣列。

      • node_start_pfn:節點起始頁面框架號。

      • node_present_pages:節點內可用實體頁面總數。

      • node_spanned_pages:節點覆蓋的頁面總數(包括空洞)。

      • kswapd_waitkswapd 等:與頁面回收和交換相關。

    • 應用: 在伺服器中,透過最佳化節點間記憶體分配,減少遠端存取延遲,提升效能。例如,運行高併發應用的伺服器可以透過 NUMA 最佳化降低記憶體存取瓶頸。

  • 3.2 區域 (Zone)

    • 描述: 每個節點進一步劃分為多個區域,儲存在 node_zones 中;node_zonelists 以鏈結串列形式儲存備用節點和區域資訊;nr_zones 表示區域總數。

    • 區域類型:

      • ZONE_DMA:用於直接記憶體存取 (DMA),適用於硬體資料傳輸,解放 CPU 資源。

      • ZONE_NORMAL:直接映射區,覆蓋核心態的低位址空間(32 位元系統中為前 896MB)。

      • ZONE_HIGHMEM:高端記憶體區,適用於 32 位元系統的高位址空間,64 位元系統通常無需此區域。

      • ZONE_MOVABLE:可移動區域,透過劃分可移動和不可移動分配區域,減少記憶體碎片。

    • 結構: 透過 zone 結構體管理,包含以下關鍵欄位:

      • zone_start_pfn:區域起始頁面號。

      • spanned_pages:區域總共跨多少頁面。

      • present_pages:區域內真實存在的頁面數。

      • managed_pages:由夥伴系統管理的頁面數。

      • per_cpu_pageset:區分冷熱頁面(熱頁面載入到 CPU 高速快取,存取速度更快)。

    • 應用: 在伺服器中,合理配置區域類型可以最佳化記憶體分配效率,確保關鍵應用(如資料庫或 Web 伺服器)獲得足夠的記憶體資源。

  • 3.3 頁面 (Page)

    • 描述: 頁面是記憶體管理的最小單位,透過 page 結構體描述,支援多種用途。

    • 用途:

      • 整頁使用:

        • 匿名頁面:直接映射到虛擬位址空間。

        • 記憶體映射檔案頁面:關聯檔案系統,與虛擬位址空間建立映射。

      • 小塊記憶體分配: 透過 Slub Allocator 將頁面切分為小塊,適用於小記憶體分配場景。

      • 複合頁面: 將多個連續頁面視為一個大頁面,最佳化大塊記憶體分配。

    • 結構: page 結構體包含以下關鍵欄位:

      • mapping:映射資訊(匿名頁最低位為 1,檔案映射頁為 0)。

      • index:映射區的偏移量。

      • _mapcount:指向該頁的頁表數。

      • lru:用於頁面交換的鏈結串列。

      • s_memfreelist 等:用於 Slub Allocator 的小塊記憶體管理。

    • 應用: 在伺服器中,頁面管理的效率直接影響到系統的整體效能,尤其是在處理大量小記憶體分配的場景中,如行程建立或資料結構分配。


四、頁面分配機制

Linux 透過夥伴系統 (Buddy System) 和 Slub Allocator 實作頁面分配,滿足不同場景的記憶體需求。

  • 4.1 夥伴系統 (Buddy System)

    • 描述: 適用於分配較大記憶體塊(頁面級別),透過維護多個空閒頁面鏈結串列實現高效分配。

    • 機制:

      • 每個鏈結串列中的節點包含的頁面數為 2 的冪次方,即第 i 個鏈結串列的每個節點擁有 2^i 個頁面。

      • 當請求分配 (2^(i-1), 2^i] 數目的頁面時,按照 2^i 頁面請求處理,並將其分裂。

      • 如果當前鏈結串列無空閒頁面,則從更大的頁面鏈結串列中找尋並分裂。

    • 實作: 透過 alloc_pages() 函數實作,參數包括:

      • gfp_mask:分配區域標誌(如 GFP_KERNEL 分配 ZONE_NORMALGFP_HIGHMEM 分配高端記憶體等)。

      • order:分配 2^order 個頁面。

    • 最佳化技術: 交叉存取 (interleaved memory) 將記憶體分為多個模組,類似負載平衡逐個寫入,提高讀寫速度。

    • 應用: 在伺服器中,夥伴系統用於大規模記憶體分配,如虛擬機器或容器的記憶體分配,確保高效的記憶體利用。

  • 4.2 Slub Allocator

    • 描述: 適用於小塊記憶體分配,將從夥伴系統申請的大塊頁面切分為小塊,儲存在快取中。

    • 機制:

      • 每個 Slub 快取區 (kmem_cache) 對應一種物件類型(如 task_struct)。

      • 透過 kmem_cache_cpu(快速分配路徑)和 kmem_cache_node(慢速分配路徑)實作分配。

    • 分配流程:

      1. 快速路徑: 從 kmem_cache_cpu 的 freelist 取得空閒物件。

      2. 慢速路徑: 當快速路徑失敗時,從 kmem_cache_node 的 partial 鏈結串列取得,或向夥伴系統請求新頁面。

    • 實作: 透過 kmem_cache_alloc_node() 和 kmem_cache_free() 管理分配和釋放。

    • 應用: 在伺服器中,Slub Allocator 的效能最佳化對於頻繁的小記憶體分配(如行程建立、資料結構分配)至關重要,特別是在高併發場景下。


五、核心頁表

核心頁表是 Linux 記憶體管理的核心元件,負責虛擬位址到實體位址的映射。

  • 5.1 初始化

    • 描述: 在系統啟動時,透過 setup_arch() 呼叫鏈初始化核心頁表。

    • 關鍵步驟:

      1. 載入 swapper_pg_dir(核心頂級頁目錄)。

      2. 透過 init_mem_mapping() 呼叫鏈(如 init_memory_mapping() -> kernel_physical_mapping_init())建立虛擬位址和實體位址的映射。

      3. 使用 __va 和 __pa 函數進行位址轉換,並透過 CR3 暫存器啟用頁表。

    • 應用: 在伺服器中,快速的頁表初始化確保系統能夠迅速進入運行狀態,支援高效的服務啟動。

  • 5.2 映射

    • 描述: 核心頁表透過多級頁表(如 pgdpudpmdpte)實作虛擬到實體位址的映射。

    • 關鍵結構:

      • swapper_pg_dir:指向頂級頁目錄。

      • level4_ident_pgt:直接映射區頁表。

      • level4_kernel_pgt:核心程式碼區頁表。

    • 特點:

      • 直接映射區 (ZONE_NORMAL) 透過偏移量實作實體位址和虛擬位址的快速轉換。

      • 高端記憶體區 (ZONE_HIGHMEM) 透過高端記憶體映射機制支援。

    • 應用: 在伺服器中,頁表映射的效率直接影響到記憶體存取速度,尤其在處理大記憶體和高併發場景時。


六、頁面交換

由於虛擬記憶體遠大於實體記憶體,Linux 透過頁面交換機制管理記憶體不足的情況。

  • 6.1 被動頁面回收

    • 描述: 當實體記憶體不足時,透過 get_page_from_freelist() 呼叫鏈嘗試回收頁面。

    • 機制:

      • 檢查 LRU (最近最少使用) 列表,優先回收不活躍頁面。

      • 對於匿名頁面,分配 swap 空間,將頁面寫入檔案系統。

      • 對於檔案映射頁面,將記憶體中的修改寫回檔案系統。

    • 實作: 透過 node_reclaim() -> __node_reclaim() -> shrink_node() 呼叫鏈實作。

    • 應用: 在伺服器中,被動回收是防止記憶體耗盡的最後防線,確保系統在高負載下保持穩定。

  • 6.2 主動頁面管理

    • 描述: 核心執行緒 kswapd 定期掃描記憶體,根據水位 (watermark) 觸發記憶體回收。

    • 水位:

      • pages_min:最小閾值,僅核心可分配記憶體。

      • pages_low:低閾值,觸發記憶體回收。

      • pages_high:高閾值,記憶體壓力小。

    • 計算:

      • pages_low = pages_min * 5/4

      • pages_high = pages_min * 3/2

    • 實作: 透過 balance_pgdat() -> kswapd_shrink_node() -> shrink_node() 呼叫鏈實作,shrink_node_memcg() 管理 LRU 列表,優先回收不活躍頁面。

    • 應用: 在伺服器中,主動管理確保記憶體始終處於健康狀態,支援長期穩定運行。


七、總結

Linux 的分頁機制是其記憶體管理系統的核心,涵蓋了從記憶體模型到頁面分配、頁表映射和頁面交換的各個方面。

  • 透過平坦記憶體模型、SMP 和 NUMA 的靈活支援,Linux 能夠適應不同的硬體架構。

  • 透過節點、區域和頁面的層次劃分,實現高效的記憶體管理。

  • 透過夥伴系統和 Slub Allocator,滿足大塊和小塊記憶體分配需求。

  • 透過核心頁表頁面交換機制,確保虛擬記憶體的高效使用。

香港伺服器等高效能計算環境中,這些機制不僅確保了記憶體的高效利用,還為高密度資料中心提供了穩定可靠的運行基礎。透過理解這些原理,系統管理員和開發者可以更好地最佳化伺服器效能,滿足現代應用的需求。


參考資料:

  • Linux 核心記憶體管理

  • Linux 記憶體管理相關資料結構

  • Linux 分頁機制概述