关注了就能看到更多这么棒的文章哦~
Cloning into a control group
By Jonathan Corbet
December 20, 2019
原文来自:https://lwn.net/Articles/807882/
Linux control-group机制(即cgroup)是用来把简化进程加入某个组里面去的操作,或者在组之间移动。用了cgroup之后,这些操作就简化成只要在cgroup文件系统目录里面相应的cgroup.procs文件里写入PID(进程ID)即可。不过,这只对已经存在的进程有效。Christian Brauner提出了一组patch来支持在创建一个新进程的时候就把它放入cgroup。
讨论实现细节之前,肯定有人要问为什么需要这个功能,毕竟cgroup用到现在也都没有用过这个功能。其实原因是目前的kernel对于基于cgroup的进程管理器来说有race condition风险。进程管理器可以创建进程,加入group,不过它没法限制在这两点之间的进程行为。例如,这个进程可能在加入某个group从而进行资源统计之前就已经执行了一段了。这个问题其实并不大,不过希望获取精确统计信息的人们对此一直觉得很别扭。
如果在进程诞生时就把他放到合适的cgroup里去,就不会有这个问题了。这样也可以支持在进程创建时就把它放到一个frozen group里,这样它的初始状态就是frozen状态,在进程管理器允许它执行之前都不会运行了。此外,按Brauner所说,可以“简化容器创建以及逻辑执行的过程”。
只有cgroup v2才可以支持在clone进程的时候直接加入cgroup,并且需要调用最新加入的clone3()系统调用:
int clone3(struct clone_args *args, size_t size);
因为clone3()里面所有参数都是放到一个结构里面的,所以函数原型非常简单,也增加了可扩展性。这个patch就利用了这一点,对struct clone_args增加了一个新的成员:
u64 cgroup;
这个成员当然会增大clone_args结构的size。对clone3()的调用都需要传入size参数来指定clone_args结构的长度,这样kernel就可以确定调用者传入的结构是否包含cgroup成员。因此,新加的cgroup成员完全不会破坏原有代码的兼容性。
如果希望创建的进程加入其他cgroup(而不是父进程的cgroup),那么就把对应的cgroup目录的文件描述符作为cgroup成员变量的内容传递进来,并且对flag成员设置CLONE_INTO_CGROUP标志。正常的话,子进程创建出来时就会在指定的cgroup里,否则调用就会失败。
用这种方式把进程加入cgroup的话,也需要遵守其他那些正常规则。例如,进程只可以被放入叶子节点,而不可以放入中间层的节点,否则也会报错。类似的,进程的所有线程通常也需要放入相同的cgroup里(不过thread mode在某些情况下可以不遵循这一点),所以线程们如果被错误地分开了,也会报错。
这组patch set还是刚刚出炉的,第一次发布出来,社区肯定还需要一些时间来review。此功能确实有用,所以预计不会有太多反对。这一版是否能通过review还需要拭目以待。不过很大可能它可以在近期合入upstream。
全文完
LWN文章遵循CC BY-SA 4.0许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注LWN深度文章以及开源社区的各种新近言论~