当前位置:首页>Linux>kswapd 工作原理:Linux 后台内存回收线程解析

kswapd 工作原理:Linux 后台内存回收线程解析

  • 2026-10-11 08:42:01
kswapd 工作原理:Linux 后台内存回收线程解析
先看一个框架图,有疑问我们一起在评论区讨论

第 1 章:kswapd 的作用

1.1 背景

    Linux 内存管理设计中,物理内存由页(page)为单位管理。系统运行过程中,应用程序会不断申请内存,导致可用的页会逐渐的减少。当可用页不足时,如果没有回收机制,内存分配将失败,可能触发 OOM(Out Of Memory)杀手,这也是我们设备常遇到的问题,我经常遇到,不知道朋友们有遇到过没有。

    kswapd 是为了解决这种长期后台内存压力问题。它是内核在每个内存节点(NUMA Node)中启动的低优先级守护线程,主要负责扫描内存页,回收不活跃页以维持系统稳定性。kswapd 背后的理念是“预防式回收”:当内存压力尚未达到紧急状态时,通过后台回收释放页,保证应用程序在分配内存时不用等待。

    kswapd 的工作涉及 LRU 链表管理、脏页写回、Page Cache 回收和匿名页回收。内核将内存页分为 Active/Inactive 链表,通过 kswapd 定期扫描 Inactive 链表,将冷页回收或写回磁盘;同时结合 direct reclaim 机制处理急需内存分配的场景。kswapd 与页面回收机制紧密结合,是 Linux 内存管理的核心守护线程之一。


1.2 kswapd 与直接回收(Direct Reclaim)关系

    Linux 内核存在两种主要回收策略:后台回收(kswapd)和直接回收(direct reclaim)。后台回收由 kswapd 触发,低优先级运行,周期性扫描内存并回收冷页;直接回收由触发内存分配失败的进程主动执行,优先级高,保证分配请求能够及时满足。

    这两种机制形成互补:kswapd 预回收,避免内存耗尽;direct reclaim 补救,保证紧急分配。内核通过 mm_flags 和 vm_pressure 指标监控内存压力,并根据压力等级决定回收策略。结合 LRU 链表管理,kswapd 能够在后台平滑释放 Page Cache、匿名页和 slab 缓存,实现内存可用性与 I/O 性能的平衡。

kswapd 工作流程:

┌─────────────┐│ 内存压力监控 │└───────┬─────┘        │        ▼┌─────────────┐│ 启动 kswapd  │└───────┬─────┘        │ 扫描节点 LRU 链表        ▼┌─────────────┐│ 回收冷页/脏页│└───────┬─────┘        │ 写回磁盘/释放内存        ▼┌─────────────┐│ 可用内存增加 │└─────────────┘
第 2 章:内存压力指标与 kswapd 启动条件

2.1 内存压力检测机制

Linux 内核通过多个指标检测内存压力。核心指标包括:

  1. free pages:系统当前可用页数量。

  2. watermark(水位):内核为不同优先级内存分配设定的阈值,分为 min、low、high 三档,这个在/proc下可以查看的。

  3. vm_pressure:根据内存消耗速率和剩余页数量动态计算压力等级。

kswapd 启动条件通常为可用内存低于 low watermark,但高于 min,此时无需阻塞应用程序,可以安全后台回收。若内存低于 min,则触发 direct reclaim,由申请内存的进程主动回收页。

    这种多层次压力检测实现了内存管理的柔性调度:后台守护线程预防内存耗尽,而应用进程在紧急情况下仍能及时回收所需内存。


2.2 NUMA 与节点级 kswapd

    在 NUMA(Non-Uniform Memory Access)架构中,每个节点拥有独立内存。Linux 为每个节点启动独立 kswapd,扫描本节点的 LRU 链表并回收本地页。跨节点访问可能引入远程内存访问延迟,因此内核优先回收本地节点冷页。

    节点级 kswapd 避免了远程内存访问对性能的负面影响。kswapd 会结合内存分配策略(如 ZONE_NORMAL、ZONE_HIGHMEM)按优先级扫描冷页,同时考虑脏页写回批量大小和回收速率,确保系统整体平衡。

NUMA 节点回收流程:

NUMA Node 0                NUMA Node 1┌─────────────┐          ┌─────────────┐│ kswapd 0     │          │ kswapd 1     │└───────┬─────┘          └───────┬─────┘        │                          │        ▼                          ▼  ┌─────────────┐            ┌─────────────┐  │ 扫描本地 LRU │            │ 扫描本地 LRU │  └───────┬─────┘            └───────┬─────┘          │                          │          ▼                          ▼   回收冷页/写回脏页         回收冷页/写回脏页

第 3 章:LRU 链表与内存回收逻辑

3.1 Active 与 Inactive 链表

    Linux 将内存页分为 Active 和 Inactive 链表。Active 链表包含近期访问频繁的页,Inactive 链表包含冷页。kswapd 的扫描重点在 Inactive 链表,通过以下步骤回收:

  1. 遍历 Inactive 链表页。

  2. 对于匿名页(Heap/Stack),尝试 swap-out。

  3. 对于文件页(Page Cache),检查是否脏页,必要时写回磁盘。

  4. 将回收的页释放到 buddy system 可用页链表。

    这种设计使系统在内存压力下能够优先保留热数据,回收冷数据,提高内存分配效率,同时减少磁盘 I/O 冲击。


3.2 回收策略与脏页处理

    脏页写回是 kswapd 回收的重要环节。kswapd 会批量写回脏页以减少随机 I/O,并根据 dirty_ratio 和 dirty_background_ratio 调整回写阈值,防止写回操作过于激进导致 I/O 突发。

    kswapd 的回收策略需要平衡内存释放速度与 I/O 压力。如果回收过慢,应用分配可能阻塞;如果过快,磁盘 I/O 突发,影响整体系统性能。内核通过 LRU + 批量写回 + 优先级扫描形成高效的后台回收机制。

kswapd LRU 扫描流程:

Inactive LRU Chain┌─────────────┐│ 页1(anon)    ││ 页2(file)    ││ 页3(file,dirty) │└───────┬─────┘        │        ▼┌─────────────┐│ 区分类型     │└───────┬─────┘        │ ┌──────┴──────┐ ▼             ▼匿名页          文件页swap-out      写回磁盘

第 4 章:kswapd 与 Page Cache 协同

4.1 Page Cache 冷页回收

    Page Cache 是 Linux 内核缓存文件页的核心。kswapd 在回收 Inactive 链表时,首先扫描 Page Cache 冷页,将长时间未访问的缓存页释放到 buddy system。理论上,这种回收不会影响应用运行,因为冷页通常可从磁盘重新加载。

    kswapd 批量释放 Page Cache 页,有效降低内存压力,提高可用页数量。配合 LRU 算法和工作集理论,kswapd 能够在后台平滑回收缓存,避免突发 I/O。


4.2 脏页回写机制

对于脏页,kswapd 会按照阈值和批量写回策略执行写回操作。写回流程包括:

  1. 将脏页放入 writeback 队列。

  2. 调用 filesystem flush 回写磁盘。

  3. 页写回完成后释放到 buddy system。

    这种机制保证了数据一致性和性能平衡,同时允许系统在后台维持高命中 Page Cache,提高应用访问效率。

脏页写回:

┌─────────────┐│ 脏页标记     │└───────┬─────┘        ▼┌─────────────┐│ 写入 writeback 队列 │└───────┬─────┘        ▼┌─────────────┐│ 批量写回磁盘 │└───────┬─────┘        ▼┌─────────────┐│ 页释放到 buddy │└─────────────┘

第 5 章:kswapd 与 Direct Reclaim 协作机制

5.1 Direct Reclaim 触发条件与流程

    当应用程序分配内存时,如果可用页低于 min watermark,将触发 Direct Reclaim,由请求内存的进程主动执行回收,而非依赖后台 kswapd。Direct Reclaim 的特点是高优先级、实时性强,确保进程可以及时获得内存。

    Direct Reclaim 与 kswapd 协作形成双层防护机制:kswapd 预回收,避免内存紧张;Direct Reclaim 补救紧急情况。Direct Reclaim 回收逻辑与 kswapd 类似,也扫描 Active/Inactive LRU 链表,区分匿名页、文件页,并处理脏页写回。但不同点在于,Direct Reclaim 会阻塞调用线程,直至释放足够页。

流程:

┌───────────────┐│ 进程申请内存  │└───────┬───────┘        ▼┌───────────────┐│ 检查 free pages│└───────┬───────┘   可用页 < min ?        │   ┌────┴─────┐   ▼          ▼触发 Direct Reclaim  不触发   │   ▼扫描 Inactive LRU回收冷页/写回脏页释放到 buddy system   │   ▼分配内存成功

    这种协作机制保证了 Linux 系统在高负载下既不会频繁阻塞进程,也不会过早触发 OOM。通过合理的 watermark 设置和 Direct Reclaim 机制,系统实现了内存回收的“预防+应急”双模式策略。


5.2 kswapd 与 Direct Reclaim 优化协作

kswapd 和 Direct Reclaim 在实际执行中需要协调:

  1. 压力等级区分:kswapd 在低于 low watermark 时预回收,避免触发直接回收;Direct Reclaim 仅在可用内存低于 min watermark 时触发。

  2. 回收目标差异:kswapd 优先回收冷页和 Page Cache,减少对进程运行的干扰;Direct Reclaim 优先回收匿名页和热页,保证进程及时分配到内存。

  3. 批量写回优化:kswapd 批量写回脏页,降低 I/O 并发;Direct Reclaim 可能触发同步写回,保证内存分配成功。

理论上,这种协作机制使 Linux 在高并发、大规模内存申请场景下保持稳定。结合 LRU 链表和 NUMA 节点优先级策略,kswapd 与 Direct Reclaim 能够平滑管理内存压力,实现高性能与低延迟的平衡。

协作流程:

┌───────────────┐│ kswapd 扫描后台│└───────┬───────┘        ▼   释放冷页/脏页        │        ▼┌───────────────┐│ Direct Reclaim│└───────┬───────┘        ▼阻塞进程释放页        │        ▼分配内存成功

第 6 章:kswapd 调优策略与性能优化

6.1 内核参数调优

kswapd 的性能调优主要通过内核参数控制:

  1. watermark_water:设置 min/low/high 内存水位,影响 kswapd 和 Direct Reclaim 的触发条件。

  2. kswapd_sleep_millisecs:控制 kswapd 扫描间隔,调整后台回收频率。

  3. dirty_ratio / dirty_background_ratio:控制脏页最大占比和后台写回阈值,避免写回突发导致 I/O 压力。

  4. vfs_cache_pressure:影响 dentry、inode 缓存回收倾向,间接影响 kswapd 回收目标。

理论上,通过调整这些参数,可以实现不同场景下的内存回收优化:高性能服务器倾向保留更多缓存,减少 I/O;嵌入式或内存紧张环境倾向更激进的回收策略,保证系统稳定性。


6.2 高负载与 NUMA 优化

    在 NUMA 系统中,kswapd 的优化策略包括:

  1. 本地回收优先:kswapd 优先扫描本节点内存,减少远程访问延迟。

  2. 节点平衡扫描:若本地节点无法释放足够页,可考虑跨节点回收,但会带来访问延迟。

  3. 脏页回写批量调节:在多节点场景下,通过 writeback batching 降低 I/O 并发和延迟。

理论上,这些优化确保了 NUMA 系统在大规模内存使用、并发分配和高 I/O 压力下,kswapd 能够稳定释放内存,防止某节点内存耗尽引发整体性能下降。

NUMA 优化流程:

┌─────────────┐│ kswapd Node0 │└─────┬───────┘      ▼扫描本地 LRU  │  ▼本地冷页不足?  │  ▼跨节点扫描  │  ▼释放页到 buddy system
第 7 章:kswapd 实践出来的方法

7.1 高 I/O 系统中的 kswapd 行为

    在数据库、虚拟化、日志密集型系统中,kswapd 扫描频率和回收速率直接影响性能。例如:

  1. 大量 Page Cache 冷页会被 kswapd 回收,以便应用分配匿名页。

  2. 高并发写入会触发脏页批量写回,减少同步写压力。

  3. NUMA 节点负载不均时,kswapd 本地回收优先策略可降低远程访问延迟。

理解 kswapd 扫描逻辑和回收优先级,有助于调整 watermark、水位和 writeback 参数,从而在高 I/O 场景下维持系统稳定。


7.2 实践

  1. 监控指标:使用 vmstat、/proc/meminfo、slabtop 等观察 free pages、LRU 长度、kswapd wakeups。

  2. 合理水位设置:确保 low watermark 高于工作集峰值,避免频繁触发 Direct Reclaim。

  3. 脏页控制:调整 dirty_ratio 和 dirty_background_ratio,避免突发写回影响 I/O。

  4. NUMA 优化:在多节点系统,确保 kswapd 本地扫描优先,避免跨节点频繁访问。

kswapd 全流程 :

┌───────────────┐│ 内存压力监控  │└───────┬───────┘        ▼┌───────────────┐│ 启动 kswapd    │└───────┬───────┘        ▼扫描 Inactive LRU        │        ▼┌───────────────┐│ 区分页类型     │└───────┬───────┘   ┌────┴────┐   ▼         ▼匿名页       文件页swap-out    写回磁盘   │         │   └─────┬───┘         ▼释放页到 buddy system         │         ▼满足内存请求 → 进程继续

最新文章

随机文章