父进程终止后如何杀死所有子进程?
How to kill all child processes after parent process termination?
我可以通过父进程杀死子进程。但是如果一个父进程有多个子进程会怎样呢?
例如下面的代码,有1个父进程和6个子进程。如何在父进程终止后立即杀死其他六个子进程?
如果你 运行 这段代码,父进程在 5 seconds.After 之后终止,子进程在另外 5 秒(总共 10 秒)后终止。
但是我想在父进程之后立即杀死 6 个子进程 termination.So 父进程和 6 个子进程应该在 5 秒后终止。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if(fork() == 0)
{
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(10); //child waits 10 seconds,then it exitted.
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(5); //parent will wait 5 seconds than it will exit
printf("Parent terminated\n");
exit(0); //parent terminated.(how can I exit the the other 6 child processes too?)
}
在 Linux,您可以使用 prctl
请求通过信号(error-checking 跳过)通知您的 parent 死亡。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/prctl.h> //<<<<<<<<
#include <signal.h> //<<<<<<<<
int main()
{
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if(fork() == 0)
{
prctl(PR_SET_PDEATHSIG, SIGTERM); //<<<<<<
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(2);
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(1);
printf("Parent terminated\n");
exit(0);
//<<< Linux auto-sends the deathsignal to all children
}
对于不需要 parent 进程在其死亡时明确终止其 children 的 POSIX-compliant 解决方案,您可以使用 async-IO 管道。
Async-IO 依赖于在文件描述符事件上发送的信号。在这种情况下,只要您确保自动关闭关闭了对 pipe-end 文件的最后引用(error-checking 跳过):
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main()
{
int pipes[6][2];
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
pipe(pipes[i]); //create a pipe
if(fork() == 0)
{
//get notified on an event on the read-end (we're aiming for the EOF event)
fcntl(pipes[i][0],F_SETOWN,getpid());
ioctl(pipes[i][0], FIOASYNC, &(int){1});
for(int j=0; j<=i; j++) close(pipes[j][1]); //close all write-end ends so the refcount is 1 and the parent has the last ref
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(2);
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(1);
printf("Parent terminated\n");
exit(0);
//<<<this closes all the last write ends of the pipes and so the children will get notified with a signal
//the signal is SIGIO by default, whose default disposition is to kill the process (this can be changed by fcntl(fd,F_SETSIG,TheSignal))
}
这是一个可能更便携的解决方案。
fork(2)
系统调用将return你的子进程的PID,你可以存储PID,然后你可以使用kill(2)
向子进程发送信号并终止他们。
请注意,SIGKILL
和 SIGTERM
信号可能需要父进程的一些特权。如果它没有这样的权限,你可以向子进程发送一个SIGCONT
,并在你的子进程中修改SIGCONT
信号处理程序。
!!!警告标志
从信号处理程序使用 exit()
是不安全的。我刚刚查看了手册 man 7 signal
,发现它不是异步安全的。您可以使用 _exit
、_Exit
或 abort
一些伪代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void* handler(int sig){
_exit(0);
}
int main()
{
pid_t children[6];
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if((children[i] = fork()) == 0)
{
signal(SIGCONT,handler);
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(10); //child waits 10 seconds,then it exitted.
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(5); //parent will wait 5 seconds than it will exit
for(int i=0;i<6;i++)
kill(children[I],SIGCONT);
printf("Parent terminated\n");
exit(0); //parent terminated.(how can I exit the the other 6 child processes too?)
}
我可以通过父进程杀死子进程。但是如果一个父进程有多个子进程会怎样呢?
例如下面的代码,有1个父进程和6个子进程。如何在父进程终止后立即杀死其他六个子进程?
如果你 运行 这段代码,父进程在 5 seconds.After 之后终止,子进程在另外 5 秒(总共 10 秒)后终止。
但是我想在父进程之后立即杀死 6 个子进程 termination.So 父进程和 6 个子进程应该在 5 秒后终止。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if(fork() == 0)
{
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(10); //child waits 10 seconds,then it exitted.
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(5); //parent will wait 5 seconds than it will exit
printf("Parent terminated\n");
exit(0); //parent terminated.(how can I exit the the other 6 child processes too?)
}
在 Linux,您可以使用 prctl
请求通过信号(error-checking 跳过)通知您的 parent 死亡。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/prctl.h> //<<<<<<<<
#include <signal.h> //<<<<<<<<
int main()
{
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if(fork() == 0)
{
prctl(PR_SET_PDEATHSIG, SIGTERM); //<<<<<<
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(2);
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(1);
printf("Parent terminated\n");
exit(0);
//<<< Linux auto-sends the deathsignal to all children
}
对于不需要 parent 进程在其死亡时明确终止其 children 的 POSIX-compliant 解决方案,您可以使用 async-IO 管道。
Async-IO 依赖于在文件描述符事件上发送的信号。在这种情况下,只要您确保自动关闭关闭了对 pipe-end 文件的最后引用(error-checking 跳过):
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main()
{
int pipes[6][2];
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
pipe(pipes[i]); //create a pipe
if(fork() == 0)
{
//get notified on an event on the read-end (we're aiming for the EOF event)
fcntl(pipes[i][0],F_SETOWN,getpid());
ioctl(pipes[i][0], FIOASYNC, &(int){1});
for(int j=0; j<=i; j++) close(pipes[j][1]); //close all write-end ends so the refcount is 1 and the parent has the last ref
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(2);
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(1);
printf("Parent terminated\n");
exit(0);
//<<<this closes all the last write ends of the pipes and so the children will get notified with a signal
//the signal is SIGIO by default, whose default disposition is to kill the process (this can be changed by fcntl(fd,F_SETSIG,TheSignal))
}
这是一个可能更便携的解决方案。
fork(2)
系统调用将return你的子进程的PID,你可以存储PID,然后你可以使用kill(2)
向子进程发送信号并终止他们。
请注意,SIGKILL
和 SIGTERM
信号可能需要父进程的一些特权。如果它没有这样的权限,你可以向子进程发送一个SIGCONT
,并在你的子进程中修改SIGCONT
信号处理程序。
!!!警告标志
从信号处理程序使用 exit()
是不安全的。我刚刚查看了手册 man 7 signal
,发现它不是异步安全的。您可以使用 _exit
、_Exit
或 abort
一些伪代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void* handler(int sig){
_exit(0);
}
int main()
{
pid_t children[6];
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if((children[i] = fork()) == 0)
{
signal(SIGCONT,handler);
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(10); //child waits 10 seconds,then it exitted.
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(5); //parent will wait 5 seconds than it will exit
for(int i=0;i<6;i++)
kill(children[I],SIGCONT);
printf("Parent terminated\n");
exit(0); //parent terminated.(how can I exit the the other 6 child processes too?)
}