Linux cgroup v2 memory.swap.max 怎样限制交换空间
来源:17golang原创
时间:2026-10-23 08:59:34 336浏览 收藏
如果只想限制一个服务最多使用多少交换空间,Linux cgroup v2 应该写目标 cgroup 的 memory.swap.max,而不是把它和 memory.max 当成同一个开关。memory.max 限制的是 cgroup 的总内存使用,memory.swap.max 限制的是交换空间使用;两者可以同时设置,也可以只设置其中一个。
最小做法是:确认目标 cgroup 已启用 memory 控制器,把进程放入该 cgroup,再向 memory.swap.max 写入字节数,例如 512M。随后读取 memory.swap.current 和 memory.swap.events,用当前占用和失败计数判断配置是否真的落到了目标 cgroup。
先分清三个内存文件
memory.max 是内存使用硬上限,达到后内核会尝试回收,无法降低使用量时可能触发 cgroup 内的 OOM 处理。memory.swap.max 是交换空间硬上限;达到这个上限后,属于该 cgroup 的匿名内存不会继续被换出。memory.swap.current 只反映当前交换使用量,不是上限配置。
| 接口 | 作用 | 适合回答的问题 |
|---|---|---|
memory.max | 限制总内存使用 | 这个 cgroup 最多能占多少内存? |
memory.swap.max | 限制交换空间使用 | 这个 cgroup 最多能使用多少 swap? |
memory.swap.current | 读取当前交换占用 | 现在用了多少 swap? |
memory.swap.peak | 读取历史峰值 | 从创建或重置以来最高用过多少? |
memory.swap.events | 读取交换边界事件 | 是否碰到过 high、max 或 fail? |

确认目标 cgroup 的控制器入口
下面的示例使用一个非根 cgroup。不同发行版的挂载路径可能不同,因此先从当前 cgroup 目录和控制器列表开始确认。不要直接把命令中的路径当成所有机器都固定不变的路径。
# 查看当前进程所属的 cgroup 层级和控制器列表 CGROUP_ROOT=/sys/fs/cgroup TARGET="$CGROUP_ROOT/app-demo" # 创建一个用于示例的非根 cgroup;目录已存在时不报错 sudo mkdir -p "$TARGET" # 确认父层级允许向子层级分发 memory 控制器 cat "$CGROUP_ROOT/cgroup.controllers" cat "$CGROUP_ROOT/cgroup.subtree_control" # 让子层级获得 memory 控制器;重复写入时忽略已启用的情况 echo '+memory' | sudo tee "$CGROUP_ROOT/cgroup.subtree_control" >/dev/null # 确认目标接口已经出现;缺少它通常说明层级或控制器尚未准备好 sudo ls "$TARGET"/memory.swap.max "$TARGET"/memory.swap.current
如果目标目录里没有这些文件,先检查父 cgroup 是否允许向下分发 memory 控制器,以及当前系统是否确实挂载了 cgroup v2。不要把“目录创建成功”误认为“memory 控制器已经生效”。
写入 memory.swap.max 设置交换上限
接口接收的是字节数,也支持内核文档定义的大小格式。写入 max 表示不设置交换硬上限;写入 512M 则把该 cgroup 的交换使用上限设为 512 MiB。写入前要先确认目标 cgroup 当前交换占用,避免把限制调得低于预期并立即触发后续分配失败。
# 把服务的交换空间上限设置为 512 MiB TARGET=/sys/fs/cgroup/app-demo echo '512M' | sudo tee "$TARGET/memory.swap.max" >/dev/null # 读取回写值,确认内核接受了这个设置 sudo cat "$TARGET/memory.swap.max" # 需要取消交换硬上限时使用 max,而不是删除控制文件 echo 'max' | sudo tee "$TARGET/memory.swap.max" >/dev/null
这项设置只限制目标 cgroup 的交换使用,不会把系统全局 swap 关掉,也不会自动改变 memory.max。如果服务同时受到总内存上限约束,实际行为要结合两个文件一起判断。
用 current、peak 和 events 判断结果
配置完成后,先看当前值,再看峰值和事件计数。memory.swap.peak 记录的是创建 cgroup 或上次重置以来的最大交换使用量;memory.swap.events 则用平面键值报告交换边界相关事件,适合放进巡检脚本。
# 一次读取上限、当前占用、历史峰值和事件计数
TARGET=/sys/fs/cgroup/app-demo
for file in memory.swap.max memory.swap.current memory.swap.peak memory.swap.events; do
# 文件不存在时保留文件名,便于区分控制器未启用和数值为零
printf '\n[%s]\n' "$file"
sudo cat "$TARGET/$file"
done
# 把事件键值变成便于日志采集的单行输出
sudo awk '{printf "%s=%s ", $1, $2} END {print ""}' "$TARGET/memory.swap.events"
看到 memory.swap.current 为 0 并不表示上限没有生效,只说明当前没有被换出的匿名页。更有价值的是把 current、peak 和 events 放在同一次采集中比较,避免只盯一个瞬时值。

降低限制后为什么旧占用不会立刻归零
如果把 memory.swap.max 调低到当前交换占用以下,已有交换条目可能会逐步回收,短时间内读取到的 memory.swap.current 仍可能高于新限制。这是渐进处理的边界,不应该据此判断写入失败。反过来,把上限调高也不会主动把已经换出的页全部换回内存。
# 先记录调整前的占用,避免把观察误差当成配置错误 TARGET=/sys/fs/cgroup/app-demo BEFORE=$(sudo cat "$TARGET/memory.swap.current") printf 'before=%s bytes\n' "$BEFORE" # 将上限调低后再次读取;旧条目可能需要时间逐步回收 echo '256M' | sudo tee "$TARGET/memory.swap.max" >/dev/null sudo cat "$TARGET/memory.swap.max" sudo cat "$TARGET/memory.swap.current" # 采集事件,确认是否出现 max 或 fail,而不是只看一次 current sudo cat "$TARGET/memory.swap.events"
排查时还要注意两点:第一,子 cgroup 的交换使用会计入父层级的层次统计;第二,memory.swap.max 的作用范围是 cgroup,而不是某个单独的线程。若只把一个服务进程放入 cgroup,检查时要确认它的子进程没有留在别的层级。
常见问题
只设置 memory.swap.max 就能限制总内存吗?
不能。它只处理交换空间上限;总内存仍要看 memory.max、当前内存和回收压力。
把 memory.swap.max 写成 0 是不是关闭整个系统 swap?
不是。它只禁止该 cgroup 的匿名内存继续换出,不影响其他 cgroup 或系统范围的 swap 配置。
为什么 memory.swap.current 超过了刚写入的限制?
降低限制后,已有交换条目可能渐进回收,因此短时间内可能高于新值。应结合事件文件和连续采样判断。
memory.swap.peak 可以手动清零吗?
可以按内核接口语义向该文件写入非空内容来重置后续读取的峰值;重置前应先把旧峰值写入监控或日志。
本文示例围绕一个目标 cgroup 展开。真正接入服务管理时,先确认进程归属,再把 memory.swap.max、memory.swap.current 与 memory.swap.events 纳入同一份资源巡检记录,才能区分“没有发生交换”和“交换已经被上限阻止”。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
240 收藏
-
387 收藏
-
179 收藏
-
284 收藏
-
250 收藏
-
384 收藏
-
490 收藏
-
126 收藏
-
201 收藏
-
128 收藏
-
420 收藏
-
189 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习