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)。