c - fork() 内的 fork()

标签 c linux fork signals

有什么方法可以区分程序中不同 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/

相关文章:

python - 是否有用 C 编写的 python 模块的 fini 例程?

regex - 我怎样才能匹配所有没有用所需的 LaTeX 标记标记的短语?

c++ - 多线程服务器问题

c - 进程运行不正确

c - 消息队列。消息发送 : Invalid argument

c - 如何检查 TCP 结构中的标志是否已设置?

c - 将结构数组嵌套到另一个结构中

具有最后一个值隐式返回的 C 变体

linux - CoreOS Kubernetes 如何监控 Node 进程?

c++ - Fork() 调用 - 程序从未终止