【问题标题】:How do I fork a child to replace a finished one?我如何叉一个孩子来代替一个完成的孩子?
【发布时间】:2013-11-29 16:21:46
【问题描述】:

我正在编写一个程序,我在其中 fork n 个孩子。 在某个时候,我通过管道将 ID 发送给父级,父级应该重新生成该子级。

int main()
{
    i = 0;
    n = 5;

    pid_t* pids = malloc(n * sizeof(pid_t));

    pid_t child;
    while ((i < n) && (child = fork()) > 0)
    {
        pids[i] = child;
        ++i;
    }

    if (child > 0) //parent
    {
        //I read the ID of a child to be reforked from a pipe 
    }
    else
        if (child == 0) //child
        {
            //Send ID to the pipe
        }
        else //error
        {
        }

    return 0;
}

我试图简单地用child = fork() 重新分配父级中的子级,但这显然不是解决方案。

编辑

我将 pid 存储在一个数组中,我与一个受信号量保护的管道进行通信。 如果我收到一个数组编号,我应该用一个新的替换那个死去的孩子。

我正在尝试发布最少的代码:

    i = 0;
    n = 5;

    pid_t* pids = malloc(n * sizeof(pid_t));

    pid_t child;
    while (i < n)
    {
        child = fork();

        if (child == 0)
        {

        }
        else
            if (child < 0)
            {
                for (;;)
                {
                    //If I finish my work
                    //I send my number in the pids array (0,1,..)
                    return;
                }
                return;
            }

        pids[i] = child;
        ++i;
    }

    for (;;)
    {
        //parent
        //...I read the ID of a child to be reforked from a pipe 
        child = fork(); //pids[?] = ...
        //...
    }

【问题讨论】:

  • “refork”是什么意思? pid的管道和发送需要什么?我想弄清楚你的真正目标是什么。
  • 在帖子中添加了详细信息。
  • 什么操作系统?当孩子死亡时,会向父母发送一个 SIGCHLD 信号,它可以对此做出反应。或者更简单,但只是等待你所有的孩子,然后重新分配任何死去的孩子。
  • “信号量保护管道”似乎有点矫枉过正。如果您正在写入少量数据(小于管道缓冲区的大小),那么您的写入将是原子的(内核会自动将信号量应用于写入操作,而无需您这样做)。

标签: c fork system-calls


【解决方案1】:

你几乎拥有它。只需将您的代码再拆分一点,就可以了。

pid_t child;
while (i < n)
{
    child = fork();

    if (child == 0)
    {
        child_code();
        exit(0);
    }
    else if (child < 0)
    {
     //error handling
    }
    pids[i] = child; // will be -1 if error occured
    ++i;
}
// parent code

【讨论】:

  • 它显然有效,但我仍然不知道如何分叉一个孩子来替换一个完成的孩子。如果问题不清楚,我添加了一些细节。
  • @otisonoza 所以,如果我错了,请告诉我,你试着等到你的孩子完成后再分叉另一个?
【解决方案2】:

使用waitpid 来收集您的孩子死后的简单方法。第一个参数控制您等待的孩子。使用此方法的变体,您应该能够在当前孩子死亡时创建替换孩子。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>    

void doChildlikeStuff()
{
    pid_t childpid = getpid();

    printf("[child %d]: created\n", childpid);
    sleep(2);
    printf("[child %d]: terminating\n", childpid);
    exit(0);
}

pid_t createChild()
{
   static int MAXCHILDREN = 6; // start contrived code to end pgm on its own

   if (MAXCHILDREN)
       MAXCHILDREN--;
   else
       return(0);              // end contrived code

   pid_t pid = fork();

   if (pid == -1)
   {
      perror("fork");
      exit(1);
   }

   if (pid != 0)
       return (pid);
   else
       doChildlikeStuff();
}


int main(int argc, char *argv[])
{
    int children = 0;
    pid_t pids[3];

   for (int i = 0; i < 3; ++i)
   {
      pids[i] = createChild();
      children++;
   }

   while (children)
   {
      int pid;
      int status;

      if ((pid = waitpid(-1, &status, 0)) == -1)
      {
         perror("waitpid");
         // no more children so end pgm
         break;
      }
      else
      {
          printf("parent reaped child [%d]\n", pid);
          children--;
      }

      for (int i = 0; i < 3; ++i)
      {
         if (pids[i] == pid)
         {
             pids[i] = createChild();
             children++;
         }
      }
   }

   return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 2012-02-09
    相关资源
    最近更新 更多