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