fork() - 如何让最后的 child 终止 father/origin 进程?
fork() - How to make the last child kill the father/origin process?
我想做最后一个child的N个child(叉子生成的)来杀他爹
我试过了:
in the fork function
signal(SIGINT, processKilled);
int car_finished = 0;
for (int car = 0; car < CAR; car++) {
int pid = fork();
...
}
in the son
car_finished++;
if (car_finished == CAR-1){
kill(getppid(), SIGKILL);
}
exit(EXIT_SUCCESS);
不过最后child不杀父....
我该怎么做?我不知道。
您的问题已被 Graeme Cole in a 正确诊断:
- 每个 child 都有自己的
car_finished
副本,因此任何 child 中的计数只会达到 1
,因此如果有多个 child,信号永远不会发送。
如何解决?
您可以使用共享内存并将 car_finished
放在共享内存中。但是,您必须在进程之间同步对共享内存的访问,因此这很快就会变得笨拙(假设在提到共享内存时它并不被认为笨重)。
可能可以使用一个文件来包含 children 的计数。 children 将对文件使用(建议)锁定以防止并发访问,并且每个人都会在退出前递减计数,而将计数减少到零的人会删除文件并向 parent过程。这是非常可靠的,但不是那么快(但可能已经足够快了)。如果 child 退出而不减少计数(例如,因为它因内存故障而崩溃,或者它被发送 SIGKILL),则会出现主要问题。然后计数将永远不会变为零,因此 parent 将永远不会发出信号。
如果 parent 只是在等待 children 死亡,它应该 运行 在 wait()
循环中:
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
/* …optionally… */
printf("%d: PID %d exited with status 0x.4X\n", (int)getpid(), corpse, status);
}
exit(EXIT_SUCCESS);
如果parent正在做一些处理,child不应该发送SIGKILL;它让 parent 没有时间清理。每个 child 可以向 parent 发送一个 SIGUSR1 信号,并且 parent 的信号处理程序可以计算接收到的信号数量,并在接收到所有信号后退出。这对于完整演示来说比较繁琐,但使用 sigaction()
来设置信号处理程序。
有时,parent 可以创建一个管道,关闭写入端,并尝试从中读取。 children 将在管道开始时分别关闭管道的读取端(代码卫生——这可以省略)。 child 完成后,它退出,显式或隐式关闭管道的写入端。当最后一个 child 退出时,parent 将从 read()
得到一个 'zero bytes read' return,并且可以关闭管道(或只是终止)。
最后这些解决方案依赖于parent进程的配合。这通常是一个安全的赌注(除非家庭功能失调,parent 尽可能地帮助他们的 children)。
我想做最后一个child的N个child(叉子生成的)来杀他爹
我试过了:
in the fork function
signal(SIGINT, processKilled);
int car_finished = 0;
for (int car = 0; car < CAR; car++) {
int pid = fork();
...
}
in the son
car_finished++;
if (car_finished == CAR-1){
kill(getppid(), SIGKILL);
}
exit(EXIT_SUCCESS);
不过最后child不杀父....
我该怎么做?我不知道。
您的问题已被 Graeme Cole in a
- 每个 child 都有自己的
car_finished
副本,因此任何 child 中的计数只会达到1
,因此如果有多个 child,信号永远不会发送。
如何解决?
您可以使用共享内存并将 car_finished
放在共享内存中。但是,您必须在进程之间同步对共享内存的访问,因此这很快就会变得笨拙(假设在提到共享内存时它并不被认为笨重)。
可能可以使用一个文件来包含 children 的计数。 children 将对文件使用(建议)锁定以防止并发访问,并且每个人都会在退出前递减计数,而将计数减少到零的人会删除文件并向 parent过程。这是非常可靠的,但不是那么快(但可能已经足够快了)。如果 child 退出而不减少计数(例如,因为它因内存故障而崩溃,或者它被发送 SIGKILL),则会出现主要问题。然后计数将永远不会变为零,因此 parent 将永远不会发出信号。
如果 parent 只是在等待 children 死亡,它应该 运行 在 wait()
循环中:
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
/* …optionally… */
printf("%d: PID %d exited with status 0x.4X\n", (int)getpid(), corpse, status);
}
exit(EXIT_SUCCESS);
如果parent正在做一些处理,child不应该发送SIGKILL;它让 parent 没有时间清理。每个 child 可以向 parent 发送一个 SIGUSR1 信号,并且 parent 的信号处理程序可以计算接收到的信号数量,并在接收到所有信号后退出。这对于完整演示来说比较繁琐,但使用 sigaction()
来设置信号处理程序。
有时,parent 可以创建一个管道,关闭写入端,并尝试从中读取。 children 将在管道开始时分别关闭管道的读取端(代码卫生——这可以省略)。 child 完成后,它退出,显式或隐式关闭管道的写入端。当最后一个 child 退出时,parent 将从 read()
得到一个 'zero bytes read' return,并且可以关闭管道(或只是终止)。
最后这些解决方案依赖于parent进程的配合。这通常是一个安全的赌注(除非家庭功能失调,parent 尽可能地帮助他们的 children)。