当前位置:首页 > 文章列表 > 文章 > linux > Linux cgroup v2 怎么冻结并恢复一组进程

Linux cgroup v2 怎么冻结并恢复一组进程

来源:17golang原创 2026-10-04 13:11:00 0浏览 收藏

Linux cgroup v2 冻结一组进程的最小做法是:先把这些进程迁入同一个非根 cgroup,再向该组的 cgroup.freeze 写入 1;恢复时写入 0。不过写入只是发出请求,真正完成要看 cgroup.events 中的 frozen 是否变成目标值。

要点速览
  • cgroup.freeze 只存在于非根 cgroup,允许值为 0 和 1。
  • 冻结会覆盖当前 cgroup 及其所有后代,适合按工作负载整体暂停。
  • 冻结与恢复可能需要时间,脚本不能只检查写操作是否成功。

官方文档:https://docs.kernel.org/admin-guide/cgroup-v2.html

先用最小配方完成一次冻结和恢复

下面假设系统把统一层级挂载在 /sys/fs/cgroup,并且当前用户对示例子树有写权限。生产环境通常应在 systemd 或容器运行时明确委派的子树里操作,不要随意改动系统服务已经管理的层级。

# 确认挂载点是 cgroup v2;预期文件系统类型为 cgroup2fs。
stat -fc %T /sys/fs/cgroup

# 在有写权限的委派子树中创建一个非根 cgroup。
CG=/sys/fs/cgroup/my-workload
mkdir "$CG"

# 每次写入一个 PID;写入任意线程 ID 会迁移该进程的全部线程。
echo "$PID_A" > "$CG/cgroup.procs"
echo "$PID_B" > "$CG/cgroup.procs"

# 请求冻结当前 cgroup 及全部后代。
echo 1 > "$CG/cgroup.freeze"

# 查看 frozen 字段;变为 1 才表示冻结已经完成。
grep '^frozen ' "$CG/cgroup.events"

# 请求恢复运行,并确认 frozen 最终回到 0。
echo 0 > "$CG/cgroup.freeze"
grep '^frozen ' "$CG/cgroup.events"

如果第一条命令没有显示 cgroup2fs,或者目标目录里没有 cgroup.freeze,先不要继续写文件。常见原因是系统仍在使用 cgroup v1、查看的是错误挂载点,或者当前目录就是根 cgroup。内核文档明确规定 cgroup.freeze 和带有 frozen 字段的 cgroup.events 都属于非根 cgroup 接口。

Linux cgroup v2 中进程归属、cgroup.freeze 控制与 cgroup.events 状态确认的静态关系图
图1:目标进程先通过 cgroup.procs 归入工作 cgroup,冻结请求写入 cgroup.freeze,完成状态由 cgroup.events 的 frozen 字段确认;这是静态关系图。

为什么写入 1 之后还要读取 cgroup.events

我第一次把这段操作写进维护脚本时,最容易漏掉的就是“冻结可能不是瞬间完成”。echo 1 成功只能证明内核接受了请求,不能证明组内所有进程此刻都已经停止。内核在冻结完成后才把 cgroup.events 的 frozen 更新为 1,并触发对应的文件变更通知。

因此自动化脚本应把状态确认做成有超时的等待,而不是固定睡眠几秒:

# 等待指定 frozen 状态,超时后返回失败,避免脚本无限阻塞。
wait_frozen() {
    target="$1" # 目标状态:冻结为 1,恢复为 0。
    tries=50     # 最多等待约 5 秒。
    while [ "$tries" -gt 0 ]; do
        # 只读取内核报告的 frozen 字段,不用进程表状态猜测。
        current=$(awk '$1 == "frozen" {print $2}' "$CG/cgroup.events")
        [ "$current" = "$target" ] && return 0
        sleep 0.1 # 给异步状态转换留出时间。
        tries=$((tries - 1))
    done
    return 1 # 上层据此报警或执行回退。
}

恢复也要同样确认。向 cgroup.freeze 写 0 后,只有观察到 frozen 0,才能把该工作负载视为已经恢复。这样做还能及时发现祖先 cgroup 仍处于冻结状态的情况。

冻结范围是整棵子树,不只是目录里的直接进程

向某个 cgroup 的 cgroup.freeze 写 1,会冻结该组及所有后代 cgroup 中的进程。它和逐个对 PID 发送 SIGSTOP 的思路不同:cgroup freezer 依据层级边界管理整组工作负载,后代层级也受父组约束。

祖先规则尤其重要。如果某个祖先 cgroup 仍被冻结,即使对子组自己的 cgroup.freeze 写 0,子组也不会真正恢复。排查“写了 0 但进程不运行”时,要沿层级向上检查,而不能只看当前文件的请求值。

Linux cgroup v2 委派子树中父子 cgroup 与进程冻结覆盖边界的静态结构图
图2:父 cgroup 的冻结覆盖直接进程和后代 cgroup;可写委派子树限制了普通操作者能够组织和迁移进程的范围,这是静态结构图。

进程迁移还有两个容易忽略的事实:

  • 每次向 cgroup.procs 写入只能迁移一个进程;多 PID 要逐个写。
  • 进程可以被显式移入或移出冻结组。移入冻结组会停止,移出后会继续运行;冻结与 fork() 竞态时也可能出现成员变化。

这意味着 freezer 适合暂停一棵已经组织好的工作负载,但它不是阻止管理员迁移进程的安全边界。若操作期间不允许成员漂移,调用方还需要在自己的调度或服务管理层串行化迁移动作。

把冻结与恢复封装成可复用脚本

下面的片段只操作一个已经存在、已经获授权的 cgroup。它不负责创建或删除系统层级,因此更适合嵌入运维脚本:

#!/bin/sh
# 遇到未定义变量或命令失败立即退出。
set -eu

CG="$1"      # 第一个参数是现有 cgroup 的绝对路径。
ACTION="$2"  # 第二个参数只能是 freeze 或 thaw。

# 确认核心接口存在,避免误操作普通目录或根 cgroup。
[ -f "$CG/cgroup.freeze" ]
[ -f "$CG/cgroup.events" ]

case "$ACTION" in
    freeze)
        value=1 # 请求冻结整棵 cgroup 子树。
        ;;
    thaw)
        value=0 # 请求恢复整棵 cgroup 子树。
        ;;
    *)
        # 参数错误时给出用法并终止。
        echo "用法: $0 CGROUP_PATH freeze|thaw" >&2
        exit 2
        ;;
esac

# 提交请求;写入成功并不等于状态转换已经完成。
echo "$value" > "$CG/cgroup.freeze"

# 在超时窗口内等待内核报告目标状态。
i=0
while [ "$i" -lt 50 ]; do
    current=$(awk '$1 == "frozen" {print $2}' "$CG/cgroup.events")
    [ "$current" = "$value" ] && exit 0
    sleep 0.1 # 每 100 毫秒复查一次。
    i=$((i + 1))
done

# 超时表明状态仍未到位,交给上层处理报警或回退。
echo "cgroup 状态切换超时: 期望 frozen=$value" >&2
exit 1

调用示例也保持简单:

# 冻结工作负载,并等待 frozen 变为 1。
./cgroup-freeze.sh /sys/fs/cgroup/my-workload freeze

# 恢复工作负载,并等待 frozen 变为 0。
./cgroup-freeze.sh /sys/fs/cgroup/my-workload thaw

权限、systemd 与委派边界

直接在 /sys/fs/cgroup 下创建目录通常需要较高权限,而且 systemd 管理的主机已经在维护自己的层级。更稳妥的做法是让服务管理器或容器运行时提供一个委派子树,再在该范围内创建子 cgroup、迁移进程和写入核心接口。

内核的委派模型不仅要求目标 cgroup.procs 可写;对非 root 用户迁移进程时,还要求操作者能够写源组与目标组共同祖先的 cgroup.procs。所以看到 Permission denied 时,不要只检查目标文件权限,还要检查迁移路径是否跨出了委派边界。

常见故障怎么判断

现象优先检查处理方向
没有 cgroup.freeze是否为 cgroup v2、是否位于根 cgroup找到统一层级并创建非根子组
写入时报 Permission denied目录、目标 cgroup.procs、共同祖先权限使用正确的委派子树
写 1 后 frozen 仍为 0是否仍在异步转换、是否等待超时读取 cgroup.events,不用固定 sleep 代替确认
写 0 后进程仍不运行祖先 cgroup 是否被冻结沿父层级检查并恢复祖先
部分 PID 没进组是否把多个 PID 一次写入逐个写入并复查 cgroup.procs

冻结前后的核对清单

  1. 确认目标位于 cgroup v2 的非根、可写委派子树。
  2. 逐个迁移 PID,再读取 cgroup.procs 核对成员。
  3. 写入 cgroup.freeze 后等待 cgroup.events 达到目标状态。
  4. 恢复失败时检查祖先层级和是否发生了进程迁移。
  5. 把等待逻辑设置超时,并让上层记录失败与回退动作。

小结:cgroup v2 冻结一组进程并不复杂,真正可靠的关键是把“写入请求”和“状态完成”分开:用 cgroup.procs 组织进程,用 cgroup.freeze 发出冻结或恢复请求,再以 cgroup.events 的 frozen 字段作为完成依据。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
mifun乐园图片权限怎么理解?隐私政策中的缓存、选图与上传边界说明mifun乐园图片权限怎么理解?隐私政策中的缓存、选图与上传边界说明
上一篇
mifun乐园图片权限怎么理解?隐私政策中的缓存、选图与上传边界说明
Go csv.Reader.LazyQuotes 会接受哪些非标准引号
下一篇
Go csv.Reader.LazyQuotes 会接受哪些非标准引号
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之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模型性能。
    325次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    383次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    376次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    343次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    167次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码