news 2026/5/12 22:12:25

Linux通过cgroups限制进程的cpu、内存使用率

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux通过cgroups限制进程的cpu、内存使用率

脚本内容

一、

ubuntu@ccpp:~/lihuiqin/oci_oracle$ ./linux_cgroups_v2.sh===Kernel 编译脚本启动(tinyconfig + 资源限制)======设置 cgroup 资源限制===tee: /sys/fs/cgroup/kernel_limit/cpu.max: Permission denied

是因为这一句:

echo"${QUOTA_US}${PERIOD_US}"|sudotee"${CGROUP_PATH}/cpu.max">/dev/null

正常情况下,cgroup v2 的:

/sys/fs/cgroup/kernel_limit/cpu.max

是可以反复写的。

我运行下面的命令:

ubuntu@ccpp:~/lihuiqin/oci_oracle$cat/sys/fs/cgroup/kernel_limit/cgroup.procs#只查看目录本身信息,不显示里面的文件ubuntu@ccpp:~/lihuiqin/oci_oracle$ls-ld/sys/fs/cgroup/kernel_limit drwxr-xr-x2root root0May1116:53 /sys/fs/cgroup/kernel_limit

从这两个输出看:

cat/sys/fs/cgroup/kernel_limit/cgroup.procs

是空的,说明这个 cgroup 里没有残留进程

drwxr-xr-x2root root0May1116:53 /sys/fs/cgroup/kernel_limit

说明目录确实存在,属主是 root,这也正常。

所以结论是:

不是因为上次 make 进程残留导致 cpu.max 不能写。

更可能的原因是:/sys/fs/cgroup/kernel_limit/cpu.max这个文件本身不存在,原因通常是父 cgroup 没有启用 cpu controller
cpu.max不存在时,sudo tee会尝试“创建”这个文件,但 cgroupfs 不允许用户创建控制文件,于是就报:

Permission denied

你先检查一下 cpu.max 是否存在

运行:

ls-l/sys/fs/cgroup/kernel_limit

重点看里面有没有:

cpu.max memory.max memory.swap.max

如果没有cpu.max,那就基本确定是父级没有启用cpucontroller。


再检查父级 controller 状态

运行:

cat/sys/fs/cgroup/cgroup.controllerscat/sys/fs/cgroup/cgroup.subtree_control

你大概率会看到第一行有:

cpuset cpu io memory hugetlb pids rdma misc

但是第二行可能没有:

+cpu +memory

或者至少没有cpu


你现在这个情况的判断

根据你贴的结果:

cgroup.procs 是空的 kernel_limit 目录存在

所以不是 make 没清理干净。

最可能是这个:

/sys/fs/cgroup/kernel_limit/cpu.max

还没生成,因为父级没有启用 cpu controller。

你可以直接运行:

ls-l/sys/fs/cgroup/kernel_limit/cpu.max

如果返回:

No such file or directory

那就完全对上了。


如果启用 controller 也失败

如果执行:

echo'+cpu'>/sys/fs/cgroup/cgroup.subtree_control

也失败,那就说明 Ubuntu/systemd 对根 cgroup 管理比较严格。
这种情况下建议直接改用:

systemd-run--scope

也就是不用自己写/sys/fs/cgroup/kernel_limit/cpu.max,由 systemd 创建和管理 cgroup。这个在 Ubuntu 上通常更省心。

二、

1,查看kernel_limit目录内容

ubuntu@ccpp:~/lihuiqin/oci_oracle$ls-l/sys/fs/cgroup/kernel_limit total0-r--r--r--1root root0May1115:49 cgroup.controllers -r--r--r--1root root0May1115:49 cgroup.events -rw-r--r--1root root0May1115:49 cgroup.freeze --w-------1root root0May1115:49 cgroup.kill -rw-r--r--1root root0May1115:49 cgroup.max.depth -rw-r--r--1root root0May1115:49 cgroup.max.descendants -rw-r--r--1root root0May1115:49 cgroup.pressure -rw-r--r--1root root0May1116:54 cgroup.procs -r--r--r--1root root0May1115:49 cgroup.stat -rw-r--r--1root root0May1115:49 cgroup.subtree_control -rw-r--r--1root root0May1115:49 cgroup.threads -rw-r--r--1root root0May1115:49 cgroup.type -rw-r--r--1root root0May1115:49 cpu.pressure -r--r--r--1root root0May1115:49 cpu.stat -r--r--r--1root root0May1115:49 cpu.stat.local -rw-r--r--1root root0May1115:49 io.pressure -r--r--r--1root root0May1115:49 memory.current -r--r--r--1root root0May1115:49 memory.events -r--r--r--1root root0May1115:49 memory.events.local -rw-r--r--1root root0May1115:49 memory.high -rw-r--r--1root root0May1115:49 memory.low -rw-r--r--1root root0May1116:53 memory.max -rw-r--r--1root root0May1115:49 memory.min -r--r--r--1root root0May1115:49 memory.numa_stat -rw-r--r--1root root0May1115:49 memory.oom.group -r--r--r--1root root0May1115:49 memory.peak -rw-r--r--1root root0May1115:49 memory.pressure --w-------1root root0May1115:49 memory.reclaim -r--r--r--1root root0May1115:49 memory.stat -r--r--r--1root root0May1115:49 memory.swap.current -r--r--r--1root root0May1115:49 memory.swap.events -rw-r--r--1root root0May1115:49 memory.swap.high -rw-r--r--1root root0May1116:53 memory.swap.max -r--r--r--1root root0May1115:49 memory.swap.peak -r--r--r--1root root0May1115:49 memory.zswap.current -rw-r--r--1root root0May1115:49 memory.zswap.max -rw-r--r--1root root0May1115:49 memory.zswap.writeback -r--r--r--1root root0May1115:49 pids.current -r--r--r--1root root0May1115:49 pids.events -rw-r--r--1root root0May1115:49 pids.max -r--r--r--1root root0May1115:49 pids.peak

2,目录里面确实缺少 cpu.max

这个输出已经把原因基本定位了:

结论

/sys/fs/cgroup/kernel_limit/里面没有cpu.max文件

你现在目录里有:

cpu.pressure cpu.stat cpu.stat.local

但是没有:

cpu.max cpu.weight cpu.uclamp.min cpu.uclamp.max

所以之前这句:

echo"${QUOTA_US}${PERIOD_US}"|sudotee"${CGROUP_PATH}/cpu.max"

实际上是在尝试写一个不存在的 cgroup 控制文件。
cgroupfs 不允许你手动创建cpu.max,所以报:

Permission denied

不是因为你第二次写入被拒绝,也不是因为里面有残留进程。


根本原因

你的kernel_limit子 cgroup 里面有memory.maxmemory.swap.max,说明memory controller 已经可用

但是没有cpu.max,说明:

父级 cgroup 没有启用cpucontroller 给子 cgroup 使用。

也就是/sys/fs/cgroup/cgroup.subtree_control里面大概率没有:

+cpu

你现在先运行这两个命令看一下

cat/sys/fs/cgroup/cgroup.controllerscat/sys/fs/cgroup/cgroup.subtree_control

如果第一行有:

cpu

但第二行没有:

cpu

那就说明 CPU controller 存在,但没有启用给子 cgroup。


三、

1,查看cgroup下的controllers和subtree_control
ubuntu@ccpp:~/lihuiqin/oci_oracle$cat/sys/fs/cgroup/cgroup.controllers cpuset cpu io memory hugetlb pids rdma misc ubuntu@ccpp:~/lihuiqin/oci_oracle$cat/sys/fs/cgroup/cgroup.subtree_control memory pids
2,定位问题:cgroup没有把 cpu 下放给 /sys/fs/cgroup/kernel_limit;
cat/sys/fs/cgroup/cgroup.controllers cpuset cpu io memory hugetlb pids rdma misccat/sys/fs/cgroup/cgroup.subtree_control memory pids

意思是:

  • 系统支持cpucontroller;
  • 但当前根 cgroup 只把memorypids下放给子 cgroup;
  • 没有把cpu下放给/sys/fs/cgroup/kernel_limit
  • 所以你的kernel_limit目录里没有cpu.max
  • 因此写/sys/fs/cgroup/kernel_limit/cpu.max会失败。

先试这个修复命令

直接运行:

sudosh-c' echo "+cpu" > /sys/fs/cgroup/cgroup.subtree_control cat /sys/fs/cgroup/cgroup.subtree_control ls -l /sys/fs/cgroup/kernel_limit/cpu.max '

如果成功,你应该看到:

memory pids cpu

或者类似:

cpu memory pids

然后:

/sys/fs/cgroup/kernel_limit/cpu.max

应该存在。

接着测试写入:

sudosh-c'echo "20000 100000" > /sys/fs/cgroup/kernel_limit/cpu.max'cat/sys/fs/cgroup/kernel_limit/cpu.max

如果显示:

20000 100000

就说明 CPU 限制可以正常用了。


四、

1,添加cpu到subtree_control
ubuntu@ccpp:~/lihuiqin/oci_oracle$sudosh-c' echo "+cpu" > /sys/fs/cgroup/cgroup.subtree_control cat /sys/fs/cgroup/cgroup.subtree_control ls -l /sys/fs/cgroup/kernel_limit/cpu.max 'cpu memory pids -rw-r--r--1root root0May1118:03 /sys/fs/cgroup/kernel_limit/cpu.max
2,问题已经解决
cpu memory pids -rw-r--r--1root root0May1118:03 /sys/fs/cgroup/kernel_limit/cpu.max

说明:

  1. 根 cgroup 的cpucontroller 已经成功启用;
  2. /sys/fs/cgroup/kernel_limit/cpu.max已经生成;
  3. 现在脚本可以正常写入 CPU 限制了。

也就是说,之前报错的根因就是:

cgroup.subtree_control里没有启用cpu,所以子 cgroup 没有cpu.max文件。


现在可以先测试写入

你可以运行:

sudosh-c'echo "20000 100000" > /sys/fs/cgroup/kernel_limit/cpu.max'cat/sys/fs/cgroup/kernel_limit/cpu.max

正常应该显示:

20000100000

这就代表 CPU 20% 限制写入成功。


建议把脚本里的 cgroup 设置部分改成这个

这样以后脚本每次运行时,会自动启用+cpu+memory+pids,避免再次遇到cpu.max不存在的问题。

# 2. 设置 cgroup v2 资源限制echo"=== 设置 cgroup 资源限制 ==="CGROUP_PATH="/sys/fs/cgroup/kernel_limit"# CPU 限制 20%PERIOD_US=100000CPU_PERCENT=20QUOTA_US=$((PERIOD_US*CPU_PERCENT/100))# 内存限制# 注意:这里是 600M,不是 6000M。# 如果你确实要 6000M,把 MEMORY_MAX 改成 "6000M"。MEMORY_MAX="600M"SWAP_MAX="1G"sudosh-c" set -e # 启用父级 cgroup controller echo '+cpu' > /sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true echo '+memory' > /sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true echo '+pids' > /sys/fs/cgroup/cgroup.subtree_control 2>/dev/null || true # 如果旧 cgroup 存在,先尝试清理 if [ -d '${CGROUP_PATH}' ]; then for pid in \$(cat'${CGROUP_PATH}/cgroup.procs'2>/dev/null||true); do echo \$pid> /sys/fs/cgroup/cgroup.procs 2>/dev/null || true done rmdir '${CGROUP_PATH}' 2>/dev/null || true fi # 重新创建 cgroup mkdir -p '${CGROUP_PATH}' # 检查 cpu.max 是否存在 if [ ! -e '${CGROUP_PATH}/cpu.max' ]; then echo '错误:${CGROUP_PATH}/cpu.max 不存在,cpu controller 没有成功启用。' echo '当前 /sys/fs/cgroup/cgroup.subtree_control 内容:' cat /sys/fs/cgroup/cgroup.subtree_control exit 1 fi # 写入资源限制 echo '${QUOTA_US}${PERIOD_US}' > '${CGROUP_PATH}/cpu.max' echo '${MEMORY_MAX}' > '${CGROUP_PATH}/memory.max' echo '${SWAP_MAX}' > '${CGROUP_PATH}/memory.swap.max' "echo"资源限制已设置:CPU${CPU_PERCENT}% | RAM ≤${MEMORY_MAX}| Swap ≤${SWAP_MAX}"

你的 cleanup 函数可以继续保留

不过有一点要注意:你的 cleanup 里面如果执行了:

rmdir${CGROUP_PATH}

那么下次脚本启动时,需要重新创建 cgroup。
上面这段新版设置逻辑已经包含:

mkdir-p'${CGROUP_PATH}'

所以没问题。


现在你可以重新运行脚本

./linux_cgroups_v2.sh

如果还想确认限制是否生效,可以另开一个 SSH 窗口执行:

cat/sys/fs/cgroup/kernel_limit/cpu.maxcat/sys/fs/cgroup/kernel_limit/memory.maxcat/sys/fs/cgroup/kernel_limit/memory.swap.maxcat/sys/fs/cgroup/kernel_limit/cgroup.procs

你应该看到类似:

20000100000600M 1G

然后cgroup.procs里会有被限制的进程 PID。


小结

现在状态是正常的:

cgroup.subtree_control=cpu memory pids cpu.max 已存在

所以之前的Permission denied已经可以解释清楚并修复了。
接下来直接跑修改后的脚本即可。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/12 22:12:24

static数组定义在函数外部(静态全局数组),作用域被限制在当前源文件中,这个源文件被include到其他文件,static数组的可见性

前言 “如果 static 数组定义在函数外部(即静态全局数组),它的作用域被限制在当前源文件中”,如果这个源文件被include到其他文件,这个其他源文件中,是否可以访问这个static 数组 可以访问,但…

作者头像 李华
网站建设 2026/5/12 22:07:06

SRWE:3步掌握终极窗口分辨率自定义工具,释放你的屏幕潜力

SRWE:3步掌握终极窗口分辨率自定义工具,释放你的屏幕潜力 【免费下载链接】SRWE Simple Runtime Window Editor 项目地址: https://gitcode.com/gh_mirrors/sr/SRWE 你是否曾因游戏不支持想要的分辨率而烦恼?或是需要为不同平台制作内…

作者头像 李华
网站建设 2026/5/12 21:55:10

泰拉瑞亚整合包下载灾厄大杂烩整合包2026最新版下载

1. 游戏基础介绍 《泰拉瑞亚》是一款经典的二维像素风格沙盒冒险游戏。游戏拥有极高的自由度,玩家可以自由探索地图、收集资源、建造房屋、打造装备、挑战BOSS。凭借自由开放的玩法、丰富的道具体系和独特的冒险氛围,这款游戏长久以来备受玩家喜爱。原版…

作者头像 李华
网站建设 2026/5/12 21:53:05

使用curl命令快速测试Taotoken视频相关文案生成接口

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 使用curl命令快速测试Taotoken视频相关文案生成接口 基础教程类,为需要在无SDK环境或进行快速接口验证的开发者提供指导…

作者头像 李华
网站建设 2026/5/12 21:51:45

粒子群灰狼优化算法稀疏码设计【附代码】

✨ 长期致力于稀疏码多址接入、星型正交振幅调制、功率不平衡码本、粒子群算法、混合粒子群灰狼优化算法研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流,点击《获取方式》 (1&#xff…

作者头像 李华