当前位置:首页 > 文章列表 > 文章 > linux > Linux cgroup v2 memory.swap.max 怎样限制交换空间

Linux cgroup v2 memory.swap.max 怎样限制交换空间

来源:17golang原创 2026-10-23 08:59:34 0浏览 收藏

如果只想限制一个服务最多使用多少交换空间,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 v2 中 memory.max、memory.swap.max 与交换占用接口的关系说明图
图1:cgroup v2 内存上限、交换上限与读取接口的关系说明图;这是静态说明图,不是运行截图。

确认目标 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.current、memory.swap.peak 与 memory.swap.events 的静态观测关系图
图2:交换占用、峰值和边界事件的观测关系说明图;这是静态说明图,不是运行截图。

降低限制后为什么旧占用不会立刻归零

如果把 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 纳入同一份资源巡检记录,才能区分“没有发生交换”和“交换已经被上限阻止”。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Python shutil.copyfileobj 怎样控制大文件复制缓冲区Python shutil.copyfileobj 怎样控制大文件复制缓冲区
上一篇
Python shutil.copyfileobj 怎样控制大文件复制缓冲区
Linux cgroup v2 怎样读取进程 CPU 使用量
下一篇
Linux cgroup v2 怎样读取进程 CPU 使用量
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    613次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    652次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    684次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    645次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    474次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码