oom_adj / oom_score_adj 设置无效的 cgroup v2 memory.oom.group 规则

8次阅读

cgroup v2 废弃了 oom_adj 和 oom_score_adj 的 per-process 调控,OOM 优先级由 memory.oom.group 和 memory.max 等 cgroup 级配置决定;写入 /proc/PID/oom_score_adj 被内核忽略,属架构移除而非权限问题。

oom_adj / oom_score_adj 设置无效的 cgroup v2 memory.oom.group 规则

为什么 oom_adjoom_score_adj 在 cgroup v2 下不生效

cgroup v2 完全废弃了 v1 的 oom_adj(对应 /proc/PID/oom_adj)和 oom_score_adj(/proc/PID/oom_score_adj)的 per-process 调控逻辑。v2 把 OOM 优先级控制收归到 memory controller 层级,只认 memory.oom.group 和整体 memory.high/memory.max 等边界设置。写入任何值到 /proc/PID/oom_score_adj 不会报错,但内核直接忽略——这不是权限或路径问题,是架构层面移除。

memory.oom.group 的真实作用和常见误用

memory.oom.group 不是“开启 OOM 分组保护”,而是决定:当该 cgroup 触发 OOM 时,内核是否只 kill 本 cgroup 内的进程(1),还是允许跨 cgroup 杀(0,默认)。它不改变 OOM 选择哪个进程被杀,也不影响 oom_score_adj 的历史值。

  • 设为 1:OOM 发生时,只在当前 cgroup 子树中选 victim,哪怕其他 cgroup 更“该死”
  • 设为 0:内核按全局 oom_score 排序,可能杀掉兄弟 cgroup 里的进程
  • 必须配合 memory.max 使用才有意义;若没设内存上限,根本不会触发 cgroup-level OOM
  • 只对 direct reclaim(即真正内存耗尽)生效,不干预 memcg reclaim 或 page cache 回收

想调控某个进程的 OOM 倾向性?只能靠 cgroup v2 的层级与配额

v2 下没有 per-process OOM 权重,唯一可行路径是把目标进程放入独立 cgroup,并通过资源限制间接影响其被 kill 的概率:

  • 给关键进程建专属 cgroup:/sys/fs/cgroup/my-critical-app
  • 设宽松上限:echo "512M" > memory.max(避免过早触发 OOM)
  • echo 1 > memory.oom.group(防止它被“连坐”)
  • 非关键进程放入另一个 cgroup 并设更激进的 memory.low 或更低 memory.max,提高其被优先回收的概率
  • 注意:memory.oom.group 对 root cgroup 无效,且不能动态继承——子 cgroup 必须显式设置

验证是否真生效:别只看文件写入成功,要看 OOM 日志和实际行为

写入 memory.oom.group 成功不代表 OOM 行为如你所愿。真正判断依据只有两个:

  • dmesg 中 OOM killer 日志是否出现 Task in /my-critical-app killed(而非父路径或其它路径)
  • 当多个 cgroup 同时超限,观察是否仅 memory.oom.group=1 的那个 cgroup 内进程被 kill
  • cat /sys/fs/cgroup/my-critical-app/cgroup.events 查看 oom 字段是否递增
  • 如果 memory.maxmax(无限制),memory.oom.group 永远不会触发——这点最容易被忽略
text=ZqhQzanResources