vin*_*one 8 c unix operating-system posix process
我有一个可以fork()和exec()链中的多个进程的程序.例如:进程A - > fork,exec B - > fork,exec C - > fork,exec D.所以A是C.的曾祖父母.
现在的问题是我对进程B,C和D没有任何控制权.因此,有几件事情可能发生.
setsid()更改其进程组和会话的情况.因此,我不能依赖进程组ID或父ID来跟踪A的所有后代.是否有任何可靠的方法来跟踪所有后代?更具体地说,我想杀死所有的后代(孤儿和其他).
如果它的POSIX兼容也会很棒.
我同意caf的总体观点:如果一个进程调用setsid,则表明它想要独立生存,无论如何。你需要仔细考虑一下你是否真的想杀死他们。
话虽这么说,有时,您会希望某种形式的 \xe2\x80\x9csuper-session\xe2\x80\x9d 包含进程树。POSIX 工具箱中没有提供此类超级会话的工具,但我将提出一些解决方案。每个解决方案都有其自身的局限性,因此它们可能并不全部适用于您的情况,但希望其中一个适合您。
\n\n一个干净的解决方案是在自己的虚拟化环境中运行进程。这可以是 FreeBSD 风格的监狱、Linux cgroups或任何其他类型的虚拟化技术。这种方法的局限性在于虚拟化技术依赖于操作系统,并且进程将在稍微不同的上下文中运行。
\n\n如果系统上只有这些进程的单个实例并且您可以使用 root 参与,请以专用用户身份运行这些进程。超级会话定义为以专用用户身份运行的进程。杀死后代kill(-1, signum)(请注意,这将杀死杀手进程本身,除非它被阻止或处理信号)。
您可以使进程打开一个唯一的文件,确保FD_CLOEXEC在文件描述符上设置了该标志。然后,所有子进程都将继承打开的文件,除非它们FD_CLOEXEC在调用execve或关闭文件之前显式删除该标志。使用 or来终止进程,通过使用orfuser -k获取进程 ID 列表(在 POSIX 中,但不是。)请注意,存在竞争条件:进程可能在您调用的时间和您终止它的时间之间分叉;因此,您需要循环调用,直到不再有进程出现(直到所有进程都死掉为止,否则不要循环,因为如果其中一个进程阻塞了您的信号,这可能是一个无限循环)。fuserlsoffuserfuser -kfuserfuser
您可以生成唯一的随机字符串并使用该名称定义环境变量,或者使用众所周知的名称和该唯一字符串作为值。它将被所有后代进程继承,除非它们选择更改其环境。没有可移植的方法来根据环境搜索进程,甚至获取另一个进程的环境。在许多 Unix 变体上,您可以通过选项获取信息ps(例如ps -e在 *BSD 或ps eLinux 上);该信息可能不容易解析,但唯一字符串的存在是一个足够的指示符。与上面一样,请注意,如果后代调用太晚而您无法注意到其子级,但在您可以杀死父级之前,则fuser需要一个循环来避免竞争条件。fork
您可以使用LD_PRELOAD一个小型库来分叉一个侦听通信通道的线程,并在收到通知时终止其进程。如果进程希望了解自己的所有线程,这可能会中断进程;这仅在标准库始终是线程安全的体系结构上才有可能,并且您将错过静态链接的进程。通信通道可以是任何允许主进程广播自杀命令的通道;一种可能性是管道,其中每个后代进程执行阻塞读取,并且祖先进程关闭管道以通知后代。通过环境变量传递文件描述符编号。