fork()-如何使最后一个孩子杀死父亲/起源进程?

时间:2019-12-14 15:44:32

标签: c signals fork kill-process

我想让N个孩子中的最后一个孩子(由叉子产生)杀死他的父亲。

我尝试过:

  

在fork函数中

signal(SIGINT, processKilled);
int car_finished = 0;

for (int car = 0; car < CAR; car++) {
     int pid = fork();
     ...
}
  

在儿子

car_finished++;
    if (car_finished == CAR-1){
        kill(getppid(), SIGKILL);
    }
    exit(EXIT_SUCCESS);

但是最后一个孩子不会杀死父亲。...

我该怎么做?我不知道。

1 个答案:

答案 0 :(得分:1)

Graeme Colecomment中已经正确诊断了您的问题:

  • 每个孩子都有自己的car_finished副本,因此任何孩子中的计数都只会达到1,因此,如果有多个孩子,则永远不会发送信号。

如何解决?

您可以使用共享内存并将car_finished放在共享内存中。但是,您必须在进程之间同步对共享内存的访问,因此这很快就变得笨拙(假设提到共享内存时,它并不被视为笨拙)。

使用文件包含子项计数可能是可能的。子级将对文件使用(建议性)锁定,以防止并发访问,并且每个子级都会在退出之前减少计数,将子级减少到零将删除文件并向父进程发送信号。这是相当可靠的,但不是那么快(但是可能足够快)。如果孩子在不减少计数的情况下退出(例如,因为它由于内存故障而崩溃或被发送SIGKILL),则会出现主要问题。这样,计数将永远不会为零,因此永远不会发出父信号。

如果父母只是在等待孩子的死亡,它应该在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);

如果父级正在执行某些处理,则子级不应发送SIGKILL;它给父母没有时间清理。每个孩子都可以向父级发送一个SIGUSR1信号,并且父级的信号处理程序可以计算接收到的信号数,并在接收到所有信号后退出。完整演示起来比较麻烦,但是使用sigaction()来设置信号处理程序。

有时,父级可以创建管道,关闭写入端并尝试从中读取。孩子们会在开始时关闭管道的读取端(代码卫生-可以省略)。子级完成后,它退出,显式或隐式关闭管道的写端。当最后一个子项退出时,父项将从read()返回“读取的零字节”,并且可以关闭管道(或终止)。

这些最后的解决方案依赖于父流程的合作。通常这是一个安全的押注(除非家庭功能失调,否则父母会尽可能帮助他们的孩子)。