使用CLONE_INTO_CGROUP克隆至cpuset cgroup后task_struct属性异常问询
问题分析与解答
核心结论:cpuset_fork未处理CLONE_INTO_CGROUP确实是bug
你贴的这段cpuset_fork代码逻辑存在明显问题——它完全忽略了CLONE_INTO_CGROUP标志的场景。当你用这个标志克隆进程时,内核已经将新进程放置到你指定的目标cpuset cgroup中,但这段代码直接强制把自进程的cpus_mask和mems_allowed覆盖为父进程的配置,等于把cgroup的设置给冲掉了,这就是你看到子进程cpuset归属正确但实际调度属性不符合预期的原因。
关于CLONE_INTO_CGROUP的使用验证
虽然官方资料较少,但这个标志的核心用法是通过clone_args结构体传递目标cgroup信息:
- 调用
clone3时,必须填充clone_args的cgroup字段,要么传入目标cgroup的文件描述符(cgroup_fd),要么指定cgroup路径(cgroup_path) - 确保当前进程拥有访问目标cgroup的足够权限(比如对cpuset cgroup的写权限)
如果你的调用流程符合上述要求,那问题就出在cpuset_fork的逻辑上,并非你的使用方式有误。
修复思路
要修正这个bug,需要在cpuset_fork中判断子进程是否通过CLONE_INTO_CGROUP创建,如果是,就从子进程所属的cpuset cgroup读取正确的cpus和mems配置,而非继承父进程的。示例修改方向:
static void cpuset_fork(struct task_struct *task) { struct cpuset *cs; if (task_css_is_root(task, cpuset_cgrp_id)) return; // 检查是否为CLONE_INTO_CGROUP创建的进程 if (task->flags & PF_FORKNOEXEC && (task->clone_flags & CLONE_INTO_CGROUP)) { cs = css_cpuset(task_css(task, cpuset_cgrp_id)); set_cpus_allowed_ptr(task, &cs->cpus_allowed); task->mems_allowed = cs->mems_allowed; } else { set_cpus_allowed_ptr(task, current->cpus_ptr); task->mems_allowed = current->mems_allowed; } }
这样就能保证通过CLONE_INTO_CGROUP创建的子进程,正确应用目标cgroup的cpuset配置。
内容的提问来源于stack exchange,提问作者honor
相关产品推荐
相关产品推荐

