2. Linux 内存子系统概述

Linux 内存管理是内核最复杂、最核心的子系统之一。它负责在有限的物理内存与无限的虚拟地址空间之间建立高效、安全的映射,并确保内存资源在进程间公平分配、在压力下有序回收。理解物理内存、虚拟内存、页框、页表、内存映射及回收机制,是后续配置 sysctl 参数、控制 cache 压力的基础。

2.1 物理内存与虚拟内存

物理内存(Physical Memory)是硬件实际提供的 RAM 芯片,以字节为单位编址。内核通过 页框(Page Frame)将物理内存划分为固定大小的块(通常为 4KB)。

虚拟内存(Virtual Memory)是每个进程独立拥有的逻辑地址空间。它通过 页表(Page Table)将虚拟地址动态转换为物理地址。这种设计带来三大优势:

  • 隔离性:进程无法直接访问其他进程或内核的物理内存。
  • 简化编程:每个进程拥有连续的 32 位或 64 位地址空间,无需关心物理碎片。
  • 按需分配:只有真正访问的虚拟页才会被映射到物理页框,节省内存。
关键指标:物理内存总量、虚拟内存总量、页框大小(通常 4KB,大页可配置为 2MB/1GB)。

2.2 页框与页表

页框是物理内存的最小分配单元。内核维护一个 伙伴系统(Buddy System)来管理空闲页框,支持按 2 的幂次合并与拆分。

页表是虚拟地址到物理地址的转换表。在 x86-64 架构下,采用 4 级页表(PGD、P4D、PUD、PMD、PTE)实现多级查找,减少页表本身占用的内存。

层级 全称 作用
PGD Page Global Directory 顶级目录,指向下一级
P4D Page 4th Directory 4 级目录(x86-64 可选)
PUD Page Upper Directory 上层目录
PMD Page Middle Directory 中间目录
PTE Page Table Entry 页表项,直接映射到页框
性能提示:TLB(Translation Lookaside Buffer)是页表的硬件缓存。大页(Huge Pages)可以减少页表项数量,提升 TLB 命中率,对数据库、HPC 场景尤其重要。
虚拟地址 → 物理地址转换(4 级页表) 虚拟地址 PGD PUD PMD PTE 页框 转换过程说明 1. CPU 发出虚拟地址,MMU 硬件自动遍历页表。 2. 每级目录根据虚拟地址中的索引位找到下一级表。 3. PTE 中存储物理页框号(PFN)及权限位。 4. 若 PTE 无效(缺页),触发 Page Fault,内核加载数据。

2.3 内存映射

内存映射(Memory Mapping)是 Linux 实现文件 I/O 和进程间共享内存的核心机制。通过 mmap() 系统调用,可以将文件或设备的一部分直接映射到进程的虚拟地址空间。

  • 文件映射:将磁盘文件内容映射到内存,读写内存即读写文件,减少 read()/write() 系统调用开销。
  • 匿名映射:不关联文件,用于进程堆、栈的扩展,或通过 MAP_SHARED 实现父子进程共享内存。
  • 页缓存(Page Cache):内核自动将磁盘数据缓存在物理页框中,所有文件 I/O 都经过页缓存,大幅提升性能。
注意:页缓存是 cache 压力的主要来源。当物理内存不足时,内核必须回收页缓存,可能导致 I/O 抖动。通过 sysctl 参数(如 vm.vfs_cache_pressure)可以控制回收倾向。

2.4 内存回收机制

当系统物理内存紧张时,内核启动 内存回收(Reclaim)机制,释放可回收页框。主要回收对象包括:

回收对象 说明 回收代价
页缓存(Page Cache) 文件数据的缓存页 低(脏页需写回磁盘)
slab 缓存 内核对象缓存(如 inode、dentry) 中
匿名页(Anonymous Pages) 进程堆、栈、匿名映射页 高(需换出到 swap)

回收触发方式分为两种:

  • 直接回收(Direct Reclaim):进程在分配内存时发现空闲页不足,直接参与回收,导致延迟抖动。
  • 后台回收(kswapd):内核线程 kswapd 在后台异步扫描 LRU 链表,提前回收页框,避免直接回收。
内存回收流程 内存分配请求 空闲足够? 分配成功 直接回收 kswapd 后台回收 说明:直接回收会阻塞进程,增加延迟;kswapd 异步回收对性能影响较小。

2.5 关键数据结构:LRU 链表

内核使用 LRU(Least Recently Used) 链表管理可回收页框。每个内存区域(zone)维护两组链表:

  • 活跃链表(active list):存放近期被访问过的页框。
  • 非活跃链表(inactive list):存放长时间未被访问的页框,优先回收。

内核通过 kswapd 或直接回收时,扫描非活跃链表,将符合条件的页框回收。若非活跃链表不足,会从活跃链表尾部移动部分页框到非活跃链表头部。

调优关联:vm.swappiness 参数控制内核倾向于回收匿名页还是页缓存。值越小(如 10),越优先回收页缓存;值越大(如 100),越积极使用 swap 换出匿名页。

2.6 本章小结