我想让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);
但是最后一个孩子不会杀死父亲。...
我该怎么做?我不知道。
答案 0 :(得分:1)
Graeme Cole在comment中已经正确诊断了您的问题:
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()
返回“读取的零字节”,并且可以关闭管道(或终止)。
这些最后的解决方案依赖于父流程的合作。通常这是一个安全的押注(除非家庭功能失调,否则父母会尽可能帮助他们的孩子)。