如何限制Ubuntu中bash子进程及其子进程的CPU亲和性范围?
实现方案:利用Cgroup v1 cpuset控制器强制限制进程组CPU亲和性
在Ubuntu 18.04/20.04中,单纯使用taskset只能设置进程初始CPU亲和性,进程可通过系统调用自行修改。要实现强制限制S及其所有子进程只能使用特定CPU核心(如1-10),且进程无法突破限制,最佳方案是使用Linux Cgroup的cpuset控制器——它能从内核层面限制进程组的可用CPU范围,进程自身的亲和性修改操作无法超出该范围。
核心原理
Cgroup的cpuset控制器为进程组分配专属的CPU和内存节点集合,内核会强制校验:任何进程的CPU亲和性设置都必须是该集合的子集。即使进程主动调用sched_setaffinity修改亲和性,也只能在cpuset允许的CPU范围内选择,无法突破限制。同时,进程的子进程会自动继承父进程的Cgroup归属,无需额外配置。
具体实现步骤与示例
1. 编写根进程R的bash脚本(restrict_cpus.sh)
该脚本负责创建Cgroup、配置CPU限制、启动子进程S并将其加入Cgroup:
#!/bin/bash # 配置参数 ALLOWED_CPUS="1-10" # 允许使用的CPU核心范围 CGROUP_NAME="restricted_cpus" # Cgroup名称 CGROUP_PATH="/sys/fs/cgroup/cpuset/${CGROUP_NAME}" # 检查权限 if [ "$(id -u)" -ne 0 ]; then echo "需以root权限运行此脚本" exit 1 fi # 创建Cgroup目录 mkdir -p "${CGROUP_PATH}" # 配置cpuset参数 echo "${ALLOWED_CPUS}" > "${CGROUP_PATH}/cpuset.cpus" echo "0" > "${CGROUP_PATH}/cpuset.mems" # 单NUMA节点系统默认内存节点为0,多节点需对应调整 # 开启自动清理(当Cgroup无进程时自动删除目录) echo "1" > "${CGROUP_PATH}/notify_on_release" echo "/bin/rmdir ${CGROUP_PATH}" > "${CGROUP_PATH}/release_agent" # 启动子进程S(替换为你的实际S进程命令) echo "启动子进程S..." ./S.sh & S_PID=$! # 将S进程加入Cgroup echo "${S_PID}" > "${CGROUP_PATH}/tasks" echo "进程S(PID: ${S_PID})已被限制在CPU核心${ALLOWED_CPUS}" # 可选:等待S进程结束后退出 wait ${S_PID}
2. 编写子进程S的测试脚本(S.sh)
模拟S尝试修改自身亲和性并创建子进程的场景:
#!/bin/bash # 尝试修改自身亲和性为CPU 0(超出限制范围) echo "S进程尝试设置亲和性为CPU 0..." taskset -p 0 $$ # 查看实际生效的亲和性 echo "S进程实际CPU亲和性:" taskset -p $$ # 创建子进程s1 echo "创建子进程s1..." sleep 30 & S1_PID=$! # 查看s1的亲和性(会自动继承Cgroup限制) echo "s1进程CPU亲和性:" taskset -p ${S1_PID} # 保持进程运行以便观察 sleep 60
3. 测试运行
- 给脚本添加执行权限:
chmod +x restrict_cpus.sh S.sh - 以root权限运行R脚本:
sudo ./restrict_cpus.sh
预期结果
- S进程尝试设置CPU 0的操作会被内核拒绝,实际亲和性仍在1-10范围内。
- 子进程s1的亲和性自动继承Cgroup限制,无法使用1-10以外的CPU核心。
注意事项
- 权限要求:操作Cgroup必须以root权限执行,普通用户无权限修改Cgroup配置。
- NUMA节点配置:若为多NUMA节点服务器,需根据实际情况修改
cpuset.mems的值(可通过numactl --hardware查看内存节点编号)。 - Cgroup清理:脚本中配置的
release_agent会在Cgroup无进程时自动删除目录,避免残留;也可手动删除Cgroup目录(需确保无进程在其中)。
内容的提问来源于stack exchange,提问作者Wei Li
相关产品推荐
相关产品推荐

