1. 内存回收概述:物理内存紧张时的系统行为
当 Linux 系统物理内存不足时,内核必须主动介入,通过一系列策略回收部分页面以维持系统运行。本章首先介绍内存紧张时的系统行为、OOM Killer 的触发条件,以及页面回收的三种主要途径:直接回收、后台回收和 kswapd。
1.1 物理内存紧张时的系统行为
物理内存的分配与回收是一个动态平衡过程。当内存分配请求无法被满足时,内核会逐步升级响应策略:
| 阶段 | 触发条件 | 系统行为 |
|---|---|---|
| 正常分配 | 空闲内存充足 | 直接从伙伴系统分配物理页,无延迟 |
| 轻度紧张 | 空闲内存低于 pages_low 阈值 |
唤醒 kswapd 内核线程,异步回收页面 |
| 中度紧张 | 空闲内存低于 pages_min 阈值 |
分配路径进入直接回收(direct reclaim),同步等待 |
| 严重紧张 | 直接回收仍无法满足分配 | 触发 OOM Killer,选择进程并强制终止 |
关键阈值:内核通过
/proc/sys/vm/min_free_kbytes 控制 pages_min 的大小,pages_low 通常为 pages_min 的 2 倍,pages_high 为 pages_min 的 3 倍。这些阈值决定了 kswapd 的唤醒频率和直接回收的触发时机。
1.2 OOM Killer 触发条件
OOM(Out-Of-Memory)Killer 是内核在极端内存压力下的最后手段。其触发条件非常严格:
- 分配标志位检查:只有分配请求携带
__GFP_FS和__GFP_IO标志时,才允许进入 OOM 路径。 - 直接回收失败:内核在尝试直接回收、压缩内存、等待 kswapd 后,仍无法获得所需页面。
- 无可用 kill 候选:如果所有进程都处于不可杀状态(如内核线程、正在执行关键操作的进程),OOM Killer 会放弃并触发内核 panic。
- oom_adj 与 oom_score:每个进程的
/proc/pid/oom_adj可调整其被选中的概率,oom_score由内核根据内存占用、运行时间、进程优先级等计算得出。
注意:OOM Killer 并非“随机杀人”。内核使用
badness() 函数对进程打分,分数最高的进程被选中。root 进程、init 进程、以及设置了 OOM_DISABLE 的进程不会被 kill。
1.3 页面回收的三种主要途径
Linux 内核通过三种途径回收物理页面,它们在不同压力等级下协同工作:
- 直接回收(Direct Reclaim):分配路径同步执行,调用
try_to_free_pages(),扫描 LRU 链表并回收页面。调用者会阻塞等待。 - 后台回收(Background Reclaim):由 kswapd 内核线程异步执行,在空闲内存低于
pages_low时唤醒,回收到pages_high后休眠。 - KSwapd:每个内存节点(NUMA node)拥有独立的 kswapd 线程,负责该节点的页面换出和匿名页交换。
核心区别:直接回收是同步阻塞的,后台回收是异步非阻塞的。直接回收发生在分配路径中,而 kswapd 在后台独立运行。当系统内存压力持续升高时,直接回收的比例会显著增加,这是系统性能下降的典型信号。
1.4 内存回收整体流程
下图展示了从内存分配请求到页面回收的完整决策路径:
1.5 三种回收途径的对比
| 特性 | 直接回收 | 后台回收(kswapd) | OOM Killer |
|---|---|---|---|
| 触发时机 | 分配路径中,空闲内存 < pages_min | 空闲内存 < pages_low | 直接回收失败且无可杀进程 |
| 同步/异步 | 同步阻塞 | 异步非阻塞 | 同步(进程被强制终止) |
| 回收目标 | 满足当前分配请求 | 恢复到 pages_high 阈值 | 释放进程所有内存 |
| 性能影响 | 高(调用者等待) | 低(后台执行) | 极高(进程终止) |
| 可观测性 | /proc/vmstat 中 pgscan_direct |
/proc/vmstat 中 pgscan_kswapd |
系统日志 dmesg 记录 |
1.6 内存回收的观测指标
系统管理员可以通过以下指标判断当前内存回收状态:
/proc/meminfo:查看MemFree、MemAvailable、SwapTotal、SwapFree等基础信息。/proc/vmstat:关注pgscan_direct(直接回收扫描页数)、pgscan_kswapd(kswapd 扫描页数)、oom_kill(OOM 触发次数)。/proc/zoneinfo:查看每个内存区域(zone)的pages_min、pages_low、pages_high阈值。dmesg:OOM Killer 触发时会输出详细的进程打分信息和内存状态。
实践建议:当
pgscan_direct 持续增长且占比超过 pgscan_kswapd 时,说明系统内存压力已经很大,直接回收频繁发生,应考虑增加物理内存或调整 vm.min_free_kbytes 参数。
1.7 小结
本章介绍了 Linux 内核内存回收的宏观框架:物理内存紧张时,系统从正常分配逐步过渡到 kswapd 后台回收、直接回收,最终可能触发 OOM Killer。三种回收途径各有不同的触发条件、同步方式和性能影响。理解这些基础概念是后续深入学习 LRU 链表和页面置换机制的基石。