杀死运行系统 shell 命令的子进程
Posted
技术标签:
【中文标题】杀死运行系统 shell 命令的子进程【英文标题】:Kill a child process running a system shell command 【发布时间】:2014-04-17 21:23:58 【问题描述】:在我的父进程中,我创建了一个执行 system("find / -print") 的子进程。 从父级内部,当我尝试使用 kill(childProcPID, SIGTERM) 杀死这个子进程时,它不会立即终止。 system 命令继续在控制台上打印输出。
示例代码如下:
int main(void)
pid_t childProc = fork();
switch (childProc)
case -1:
perror("fork() error");
exit(EXIT_FAILURE);
case 0:
system("find / -print");
printf("if I use kill(pid, SIGTERM) control doesnt reach here");
exit(EXIT_SUCCESS);
default:
;
int i = 500000;
//No a great way to put sleep
//but its just temp
while (i != 0)
--i;
kill(childProc, SIGTERM);
break;
printf("Exit!!!!!!");
return EXIT_SUCCESS;
请让我知道我做错了什么或者是杀死孩子的正确方法?
【问题讨论】:
SIGKILL
可能是一个选项。
使用 SIGKILL,我得到相同的结果
有可能孩子甚至没有跑步。尝试使用 sleep(1)
而不是你的忙循环。它在<unistd.h>
。
实际上,当我运行这个程序时,我看到输出连续写在屏幕上。所以,我猜系统命令仍在运行。
我猜该程序已经完成,而您所看到的只是 I/O 子系统的输出缓冲区清空。尝试按 CTRL-O,看看是否设置为刷新。
【参考方案1】:
system
函数将自己创建一个子进程来执行命令(然后阻塞直到该子进程终止)。您所做的是杀死调用system
的子进程,而不是杀死system
产生的子进程。
【讨论】:
您确定该信号没有升级回父进程吗?换句话说,系统是否使用 setsid() 来渲染一个新的进程会话? 但是无论如何,这暗示你应该使用system
,而不是使用exec
。
我也觉得系统创建了自己的子线程。也许我应该使用 exec 家族函数
@Vinit Sharma:如果你想控制是否过早终止进程,你不能使用system
。您必须使用exec
函数之一。
@Vinit Sharma:cd
等 Shell 命令不起作用,但实际程序可以。请注意execlp
和execvp
接受文件名(因此它接受find
而不是/usr/bin/find
)。它搜索的路径取决于您的程序的环境变量。【参考方案2】:
尝试设置会话 ID 并终止进程组(man 2 kill)
int main(void)
pid_t childProc = fork();
switch (childProc)
case -1:
perror("fork() error");
exit(EXIT_FAILURE);
case 0:
setsid();
system("find / -print" );
printf("if I use kill(pid, SIGTERM) control doesnt reach here");
exit(EXIT_SUCCESS);
default:
sleep(1);
kill(childProc*-1, SIGTERM);
break;
printf("Exit!!!!!!");
return EXIT_SUCCESS;
这或多或少有效。需要注意的是,父母必须给孩子时间 setid(),因此需要睡眠。
希望对您有所帮助。
【讨论】:
是的,它确实有效......但我只是想知道它是否会导致任何其他问题? @Vinit Sharma:这个解决方案没有问题。我要说的是你不应该依赖sleep
来避免竞争条件,但在这种情况下,多久调用kill
并不重要。但是,使用exec
函数不是更优雅吗?在这里,您正在创建一个新会话,以便您可以将进程作为一个组终止。
@Vinit Sharma。你不会有额外的问题。它只会杀死进程组中的进程。但是,您也应该随意尝试 exec 函数。但是,您可能会发现,根据您对它们调用的内容,您可能仍需要 setid() 以确保传播到可能产生的任何后续第三级子级。
@someguy:谢谢..我没有在我的实际代码中使用睡眠功能......它制作了这个程序,这样我就不必复制粘贴确切的代码了。我也在试验 exec 函数。非常感谢您的投入。
@maha:非常感谢您的解释。【参考方案3】:
首先,您应该检查从kill()
返回的结果——如果返回 0,则操作成功。但是,如果返回 -1,请检查全局变量 errno
以了解问题所在。
如果信号发送成功,您唯一能做的就是确保您发送的是您想要的信号。正如@Till 在评论中指出的那样,发送SIGKILL instead of SIGTERM 会更有效,因为操作系统会处理前者,而目标进程不能忽略它。
无论如何,要意识到与其他进程的交互通常是一个异步进程——无论你做什么,目标进程都可能不会在kill()
返回时终止。
【讨论】:
感谢您的帮助,但它只是让这个程序显示我的问题。我知道我应该使用 kill 的返回值,我同意你的最后一点。以上是关于杀死运行系统 shell 命令的子进程的主要内容,如果未能解决你的问题,请参考以下文章