kswapd0 长期处于 D 状态并频繁触发 vmpressure,主因是 I/O 阻塞(如慢速 swap 设备、dirty page 未刷盘或文件系统元数据阻塞),vmpressure 仅为内存回收压力的信号而非原因;需通过栈追踪、iostat 和 /proc/swaps 综合诊断。
![进程 d 状态卡在 [kswapd0] 的 vmpressure 与 swap 压力](https://img.php.cn/upload/article/001/242/473/176982810258800.png)
为什么 kswapd0 会卡在 D 状态且持续触发 vmpressure?
kswapd0 是内核的异步内存回收线程,D 状态(uninterruptible sleep)本身正常,但长期卡住说明它正在等待 I/O 完成——通常是 swap 设备写入慢或阻塞。此时 vmpressure 事件频繁上报,不是原因而是信号:内核检测到页面回收压力陡增,已开始向用户态(如 systemd、low-memory-killer)广播内存紧张信号。
常见诱因包括:
- swap 分区位于高延迟设备(如机械盘、USB 盘、网络块设备)
- swap 被禁用但
vm.swappiness=100或类似配置仍驱使内核积极换出匿名页 - 存在大量 dirty page 未刷盘,
kswapd0在 wait_event() 中等writeback完成 - ext4/xfs 文件系统在日志提交或元数据更新时阻塞页回收路径
vmpressure 事件是否真的代表该杀进程?
不一定。Linux 的 vmpressure 是分等级的信号(low/medium/critical),仅 critical 才暗示 OOM 风险临近。很多容器运行时或 systemd 服务会监听 medium 就提前释放缓存或降级服务,造成误判。
验证方法:
- 查实时压力等级:
cat /proc/vmstat | grep -i vmpressure - 看当前状态:
cat /sys/fs/cgroup/memory/memory.vmpressure(cgroup v1)或使用systemctl show --property=MemoryPressure(systemd v249+) - 注意:若
vmpressure持续为medium但MemAvailable> 500MB,大概率是回收路径被阻塞,而非真缺内存
如何快速判断是不是 swap I/O 卡死?
直接看 kswapd0 的栈和 I/O 等待目标:
- 获取线程栈:
cat /proc/$(pgrep kswapd0)/stack,若末尾是__swap_writepage、submit_bio或wait_on_page_writeback,基本锁定 swap 写入阻塞 - 检查 swap 设备状态:
swapon --show=NAME,TYPE,SIZE,USED,PRIORITY,再用iostat -x 1观察对应设备的%util和await - 确认 swap 是否启用:若
free -h显示Swap:全为 0,但/proc/swaps非空,可能是 swap 分区已 disable 但未 umount,残留脏页无法回收
典型错误配置:vm.swappiness=200(超出合法范围 0–100),会导致内核行为异常,部分版本会静默截断为 100,但某些补丁分支可能引发回收逻辑紊乱。
临时缓解与根治建议
临时手段只能绕过阻塞点,不能替代诊断:
- 紧急停用低效 swap:
swapoff /dev/sdXN(确保Free + Buffers + Cached> 当前SwapUsed,否则触发 OOM Kill) - 降低回收激进度:
sysctl vm.swappiness=10(避免过度换出) - 加速脏页落盘:
sysctl vm.dirty_ratio=20 && sysctl vm.dirty_background_ratio=10(防止脏页堆积拖慢kswapd0)
根治必须定位 I/O 瓶颈:如果是 NVMe 盘却出现高 await,检查是否启用了 nomerges 或驱动 bug;如果是 LVM 上的 swap,确认 lvconvert --repair 无元数据损坏;容器环境则需检查是否绑定了慢速 host swap 而非使用 memory cgroup 限流。
最容易被忽略的一点:即使你没配 swap,kswapd0 仍会活跃——它负责所有 page reclaim,包括 slab、page cache 和匿名页。D 状态卡住,往往不是 swap 本身的问题,而是底层块层或文件系统在某次 writeback 中死锁或响应超时。








