我有以下情况:(以下函数取自python)
我有一个正在运行的进程 A,并且对其设置了 cgroup 内存限制。
我使用 os.fork() 从 A 分叉出一个子进程。让我们称之为 B。然后我执行 os.execvp 在 B 中加载 shell 脚本。http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/exec.html该进程与调用者(即B)运行在相同的地址空间中。
B 中运行的 shell 脚本创建一个 Java 程序,该程序以给定的堆大小无限期地运行,并在 OOM 时自动终止。这是通过通过-XX:OnOutOfMemoryError='kill -9 %p'到java命令。这将创建另一个进程 C 作为 B 的子进程。
从顶部看,我将 B 视为 A 的子级,将 C 视为 B 的子级,正如预期的那样。
以下是疑点:
cgroup 限制是否仅适用于 A、(A+B) 或 (A+B+C)?
如果达到内存限制,哪个所有进程都会被终止:A或(A+B)或(A+B+C)?为什么?是否使用进程 pid 或应用了限制的进程的地址空间来识别?
如果在上述情况下,并非所有进程都被杀死,是否有办法微调 cgroup 设置以杀死所有子进程,因为在这种情况下我们会留下孤立进程?
我正在使用Centos7作为底层操作系统。
答案1
我将回答您的每个问题:
- cgroup 适用于 A 及其所有后代。您可以进行实验来验证此行为。请考虑:
Create a new memory cgroup
# mkdir /sys/fs/cgroup/memory/example
Note the shell's PID:
# echo $$
679
Put the running shell into the new cgroup
# echo $$ > /sys/fs/cgroup/memory/example/cgroup.procs
Examine what processes are in the cgroup. Here 679 was the
shell's PID; 723 is the pid of cat
# cat /sys/fs/cgroup/memory/example/cgroup.procs
679
723
Start a new shell and note its PID
# bash
# echo $$
726
Examine what processes are in the cgroup. 679 was the original
shell. 726 is the second shell. 731 is cat:
# cat /sys/fs/cgroup/memory/example/cgroup.procs
679
726
731
- 根据内存cgroup文档:
当 cgroup 超出其限制时,我们首先尝试从 cgroup 回收内存,以便为 cgroup 触及的新页面腾出空间。如果回收不成功,则会调用 OOM 例程来选择并终止 cgroup 中最庞大的任务。
基于此,它不会杀死 cgroup 中的所有进程;它选择消耗最多内存的一个。
- 我没有找到一种方法来调整哪个进程被杀死以匹配您在这里提出的要求。有一种方法可以对 OOM 杀手进行一定程度的控制;例如,参见这个Linux 每周新闻文章。也就是说,如果其中一个父进程被杀死,它所拥有的所有子进程都会被重新设置为 PID = 1 的进程(默认情况下)。