Linux内核页缓存回收机制与内存压力调优方法 - 第2节

2.1 物理内存的层次化组织

现代计算机系统,尤其是服务器和NUMA(Non-Uniform Memory Access,非统一内存访问)架构的机器,物理内存不再是简单的线性数组。Linux内核为了高效管理、回收和调度内存,将物理内存组织为三个层次:节点(Node) → 区域(Zone) → 页(Page)。理解这一层次结构是掌握页缓存回收机制的前提。

核心观点: Linux 内存管理的核心抽象是将物理内存按“访问延迟”和“硬件约束”进行分区。NUMA节点对应CPU与内存的物理距离,Zone对应硬件寻址能力限制,Page则是内核管理的最小单元。

2.1.1 NUMA 架构与内存节点(Node)

在NUMA架构中,CPU访问本地内存(直连内存)的速度远快于访问远程内存(通过互联总线访问其他CPU的内存)。Linux内核将每个CPU及其本地物理内存抽象为一个 内存节点(pg_data_t)。

  • 本地内存访问: 延迟低,带宽高。
  • 远程内存访问: 延迟高,带宽低,且可能引发互联总线争用。
  • 内核策略: 内存分配时优先从当前CPU所在节点分配(本地分配),以提升性能。
性能提示: 在NUMA系统上,如果进程频繁访问远程节点内存,性能会显著下降。使用 numactl 命令可以绑定进程到指定CPU和内存节点,避免跨节点访问。
NUMA 架构与内存节点(Node)示意图 Node 0 CPU 0 / CPU 1 本地物理内存 (低延迟访问) pg_data_t Node 1 CPU 2 / CPU 3 本地物理内存 (低延迟访问) pg_data_t 互联总线 (远程访问) 说明:Node 0 的 CPU 访问 Node 0 内存为本地访问(快),访问 Node 1 内存为远程访问(慢)。

2.1.2 内存区域(Zone)

每个内存节点内部,根据物理地址范围和硬件限制,进一步划分为多个 区域(Zone)。Linux内核主要使用以下三种区域:

区域名称 物理地址范围 主要用途 关键约束
ZONE_DMA 0 ~ 16 MB 老式ISA设备DMA操作 地址必须低于16MB,用于兼容旧硬件
ZONE_DMA32 0 ~ 4 GB 32位设备DMA操作 地址必须低于4GB,用于现代PCIe设备
ZONE_NORMAL 16 MB ~ 896 MB (32位)
或 4GB 以上 (64位)
内核直接映射、常规内存分配 内核线性映射区,性能最佳
ZONE_HIGHMEM > 896 MB (仅32位) 用户进程页缓存、用户态内存 内核不能直接访问,需要临时映射
ZONE_MOVABLE 可变 可迁移页面(防止内存碎片) 页面可以被迁移,用于内存规整
注意: 在64位系统上,由于虚拟地址空间足够大,ZONE_HIGHMEM 已经不再使用。所有物理内存都可以被内核直接映射,因此主要使用 ZONE_DMA、ZONE_DMA32 和 ZONE_NORMAL。
内存节点内部的区域(Zone)划分 Node 0 物理内存空间 ZONE_DMA 0 - 16 MB ISA DMA ZONE_DMA32 0 - 4 GB PCIe DMA ZONE_NORMAL 4 GB 以上 内核直接映射 ZONE_MOVABLE 可变 防碎片 说明:64位系统下,ZONE_HIGHMEM 已废弃,物理内存主要分布在 ZONE_NORMAL 和 ZONE_MOVABLE。

2.1.3 物理页框(Page Frame)

物理内存最终被划分为固定大小的 页框(Page Frame),简称 页(Page)。页是内核内存管理的最小单位。

  • 默认大小: 4 KB(x86/ARM 架构)。
  • 大页(Huge Page): 2 MB 或 1 GB,用于减少TLB miss,提升大内存应用性能。
  • 内核描述: 每个物理页框对应一个 struct page 结构体,存储页的状态、引用计数、映射信息等。
关键数据结构: struct page 是内核中最重要的数据结构之一。它包含了 flags(页状态标志)、_refcount(引用计数)、mapping(指向地址空间的指针)、lru(链表节点,用于页回收)等字段。
// 简化后的 struct page 定义(位于 include/linux/mm_types.h)
struct page {
    unsigned long flags;          // 页状态标志(如 PG_locked, PG_dirty, PG_uptodate)
    atomic_t _refcount;           // 引用计数,决定页是否可以被释放
    struct address_space *mapping; // 指向该页所属的地址空间(用于文件页缓存)
    pgoff_t index;                // 在地址空间中的偏移量
    struct list_head lru;         // LRU链表节点,用于页回收算法
    union {
        struct {
            unsigned long private; // 私有数据
        };
        struct kmem_cache *slab_cache; // SLAB分配器使用
    };
    // ... 其他字段
};
物理页框(Page Frame)与 struct page 物理内存条(4 KB 页框阵列) Page 0 Page 1 Page 2 Page 3 ...... Page N 内核维护的 struct page 数组 每个物理页框对应一个 struct page,存储 flags、_refcount、mapping、lru 等元数据

2.2 层次关系总结

物理内存管理的三层结构可以总结为以下流程:

  1. 系统启动时: 内核遍历物理内存,根据NUMA拓扑创建 pg_data_t 节点。
  2. 节点初始化: 每个节点内部,根据物理地址范围划分 zone(DMA、DMA32、NORMAL、MOVABLE)。
  3. 页框管理: 每个zone管理一个 struct page 数组,每个page代表一个4KB物理页框。
  4. 分配与回收: 内存分配时,内核从当前CPU所在节点的合适zone中分配page;回收时,通过LRU链表遍历page进行回收。
调优关联: 页缓存回收机制的核心操作对象就是 page。回收算法(如LRU)遍历的是每个zone内的 LRU链表,而NUMA节点信息决定了回收时是否优先回收本地内存。理解Node/Zone/Page的层次,是后续学习内存压力调优的基础。
Node → Zone → Page 层次关系图 Node 0 (pg_data_t) ZONE_DMA struct page 数组 (管理物理页框) LRU链表 ZONE_NORMAL struct page 数组 (管理物理页框) LRU链表 ZONE_MOVABLE struct page 数组 (可迁移页) LRU链表 每个 Zone 独立管理自己的 struct page 数组和 LRU 链表,回收操作以 Zone 为单位进行。