如何使用 C 在 Linux 上以编程方式杀死进程树

Posted

技术标签:

【中文标题】如何使用 C 在 Linux 上以编程方式杀死进程树【英文标题】:How to kill a process tree programmatically on Linux using C 【发布时间】:2013-03-19 12:10:10 【问题描述】:

我正在尝试编写一个生成子进程的函数,让它运行一段时间,如果它还没有完成,则将其杀死:

int sysExecTimeout(const char * exePath, int timeoutSec);

在函数中,我使用forkexecl 生成孩子,当超时时,我在2 秒后使用kill(pid, SIGTERM)kill(pid, SIGKILL),以确保孩子死亡:

pid_t pid = fork();

if(pid == 0) 
    execl("/bin/sh", "sh", "-c", exePath);
    exit(127);
 else if(pid != -1) 
    // timeout code
    if(timeout) 
        kill(pid, SIGTERM);
        sleep(2);
        kill(pid, SIGKILL);
    

我正在使用Linux,似乎当父进程死亡时,子进程不会自动杀死。所以两个kill 调用只会杀死/bin/sh 进程并让exePath 命令运行,因为它是/bin/sh 的子进程。

我正在尝试编写sysExecTimeout 函数,以便它杀死以pid 为根的整个进程树,其中pid 是来自pid = fork() 的PID

我需要这个,因为exePath 命令会产生其他命令,这些命令也会产生其他命令,这可能会卡住并消耗资源。

我无法控制要执行的 exePath 二进制文件/脚本,因此我无法在其中编写自己的 parent-dies-so-kill-the-children 逻辑。

我尝试使用kill(0, SIGTERM),它几乎完成了这项工作,除了它也杀死了我自己的进程:)

我想知道是否可以在 C 中以编程方式打开一个标志,上面写着“嘿,伙计,当我死时,带走我所有的孩子并杀死他们,并为他们的孩子递归重复”,这样整个进程树就开始了从那个程序死掉(假设可以遵循 PID/PPID 链)。

我可以在这里使用那个标志:

if(pid == 0) 
    turnOnRecursiveDeathFlag();

    system(exePath);
    //execl("/bin/sh", "sh", "-c", exePath);
    exit(127);

有没有办法做到这一点?我已经搜索了一段时间,但我只能找到使用ps -ef 的黑客,或修改您正在运行的子进程等。

【问题讨论】:

else if(pid == -1) :这表明fork()有问题,而不是子进程.. 是的,抱歉,打错了:) 【参考方案1】:

在子进程中使用 setpgid 将其 GPID 设置为等于它自己的 PID。然后父级可以 kill(-pid,...) 向整个组发出信号。

pid_t pid = fork();

if(pid == 0) 
    setpgid(0, 0);
    execl("/bin/sh", "sh", "-c", exePath);
    exit(127);
 else if(pid == -1) 
    // timeout code
    if(timeout) 
        kill(-pid, SIGTERM);
        sleep(2);
        kill(-pid, SIGKILL);
    

应该可以的。

还有一件事,当您生成 shell 时,请确保它不会启用作业控制。否则,它将创建自己的进程组。你的“/bin/sh -c”没问题。

【讨论】:

太好了,这似乎可行,谢谢!我不确定进程组 ID 的处理是什么(这仅仅是进程的 GID 吗?),但我正在研究它。 顺便说一句,由于我无法编辑您的帖子,您应该将 setgpid 更改为 setpgid,这似乎是正确的名称。 我为他修好了@AlinTomescu...或者我猜它正在审查中

以上是关于如何使用 C 在 Linux 上以编程方式杀死进程树的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C++ 以编程方式杀死进程?

在 C# 中以编程方式杀死进程树

在 Linux 命令行上以编程方式删除所有蓝牙设备

在 Windows 上以编程方式获取每个进程的磁盘 io 统计信息?

如何用qt4编程结束linux进程

linux中怎么终止正在运行的进程