有什么方法可以区分程序中不同 fork() 函数创建的子进程。
global variable i;
SIGCHLD handler function()
{
i--;
}
handle()
{
fork() --> FORK2
}
main()
{
while(1)
{
if(i<5)
{
i++;
if( (fpid=fork())==0) --> FORK1
handle()
else (fpid>0)
.....
}
}
}
有什么方法可以区分 FORK1 和 FORK2 创建的子进程吗?因为我试图在 SIGCHLD 处理程序函数中减少全局变量“i”的值,它应该只为 FORK1 创建的进程减少。
我尝试使用数组并保存由 FORK1 创建的子进程的进程 ID,这是由父进程完成的。只有当 dead child 的进程 id 在数组中时,我才会减少 'i' 的值 ...
但我遇到了以下情况的问题
child1, parent1, child1 killed, child2, child2 killed, parent2
在 child1 的情况下,因为它在 parent1 数组正确更新后被杀死。
但是如果 child2 在它的 pid 值被数组中的 parent2 更新之前被杀死怎么办?在 SIGCHLD 信号处理函数内部,由于 child2 PID 值不在数组中,因此“i”值不会相应地减少..
那么对于这个问题有没有更好的解决方案呢??
最佳答案
由于您已经保存了一个 PID 列表,您希望在 SIGCHLD
处理程序中为其递减 i
的值,这部分可能会让您感到困惑正在更新列表时收到额外的 SIGCHLD
。
您可以使用 sigprocmask()
在执行信号处理程序期间屏蔽/阻止其他 SIGCHLD
信号。这应该为您提供足够的时间来更新您的进程 ID 数组/列表,而不必担心收到另一个 SIGCHLD
。当信号处理程序完成时,阻塞的掩码必须返回到它的原始值。
尝试向您的 SIGCHLD
处理程序添加类似于以下内容的内容:
sigset_t mask;
sigset_t orig_mask;
sigemptyset (&mask);
sigaddset (&mask, SIGCHLD);
/* temporarily mask/block SIGCHLD signals and save original mask */
if (sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0) {
perror ("sigprocmask - %s", strerror(errno));
}
/* process SIGCHLD via waitpid() and update PID list as necessary */
...
/* restore original mask */
if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) {
perror ("sigprocmask - %s", strerror(errno));
}
更新
在重新检查您的问题后,我发现您有一个竞争条件,其中子进程在父进程可以将其 PID 添加到列表之前终止。
一个可能的解决方案仍然是使用sigprocmask()
来阻止临界区中的SIGCHLD
信号。在这种情况下,您需要在调用 fork()
之前阻止 SIGCHLD
信号,并在 PID 添加到列表后在父代码中取消阻止它。如果 child 死亡,信号处理程序将在您取消阻止信号后调用,这应该保证 PID 在列表中。
关于c - fork() 内的 fork(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2401510/