如何一次只分叉一个 child

How to fork only one child at a time

我第一次尝试分叉。我有一个包含整数列表的文件,我希望每一行都派生一个 child,child 处理该行并在输出文件中写入一些内容。基本上,for 循环从输入文件中的行数开始,然后进入一个循环,每一行都应该分叉一个 child,在完成 child 之后,分叉应该启动另一个 child。我在执行此操作时遇到了麻烦,因为在第一个 child 完成其工作之前,第二个 child 开始并且在 parent 之间也在执行一些操作。

编辑:代码看起来像这样:

void dosomething(flag)
{
}
void forkingfunction(int size, int array[],char *outputfile)
{
    int i,j,starting=1,temp=1,status;

    for(i=0;i<size;i++,temp++)
        {

             pid_t pID = fork();

               if (pID == 0)                // child
               {
                   printf("\nchild pid %d\n",getpid());

                       const int count = dosomething(flag);
                       if(flag==1)
                       {
                           _exit(EXIT_SUCCESS);
                            kill(pID,SIGKILL);
                       }

                       else
                       {
                       FILE *fp;

                          fp = fopen(outputfile, "a+");
                          if (fp == NULL)
                          {perror("Unable to open the output file:");}

                           for (i = 0; i < len; i++)
                           {
                               if (solution[i])
                               {
                                       fprintf(fp," %u ",array[i]);

                               }
                           }
                           fprintf(fp,"=%d\n",sum);
                       }

                      _exit(EXIT_SUCCESS);
                       kill(pID,SIGKILL);

               }
               else if (pID < 0)            // failed to fork
               {
                   perror("Failed to fork:");
               }
               else
               {
                  // wait(NULL);
                   if ((pID = wait(&status)) == -1)
                                       {
                                           perror("Error in wait:");
                                       }
               }
        }
}
void readingfile(char *inputfile,char *outputfile)
{

    FILE *myFile = fopen(input, "r");

    if (myFile == NULL)
    {
        perror("Error: Failed to open file.");

    }
    //code to get number of lines 
    while ((c=getc(myFile)) != EOF)
    {
        //puts values of file in an array for processing
     }

    forkingfunction(size,array,output);

    // close file
    fclose(myFile);
}

int main(int argc, char **argv)
{

        readingfile(inputfilename,outputfilename);

    return 0;
}

您使用一次调用 wait():

else
{
    // wait(NULL);
    if ((pID = wait(&status)) == -1)
    {
        perror("Error in wait:");
    }
}

那(或改用 waitpid())是您问题答案的核心,但是……

  • 您需要一个与 pID 不同的变量来保存 return 值,以确保您得到正确的死 child 因为相关的 PID 在 pID 在它被破坏之前。

  • 如果您在该进程的后台有其他进程 运行,您可能会得到其中一个,而不是刚刚启动的 child,因此您需要测试wait() 上报的PID 是否正确,如果不正确再试。这意味着你需要一个像这样的循环:

    int corpse;
    int status;
    
    while ((corpse = wait(&status)) != pID && corpse != -1)    // Or corpse > 0
    {
        /* maybe report on what died */
    }
    
  • 或者可以用waitpid()直接等相关的child死掉:

    int corpse;
    int status;
    while ((corpse = waitpid(pID, &status, 0)) != pID && corpse != -1)
    {
        /* maybe report on what died */
    }
    

如果没有 children 等待,或者指定的 PID 不再存在,wait()waitpid() 调用将终止并出现错误。如果程序中其他地方的代码等待进程终止,则可能会发生这种情况。也可以处理它;当系统显示 "there are no children left" 或 "that process you asked about doesn't exist" 时,您不希望循环被锁定。如果您有 SIGCHLD 的信号处理程序并且它会等待一些时间,也会发生这种情况。

在这两种情况下,您可能需要决定如果 corpse == -1 在循环之后要做什么。它不应该发生,但是......你可以合法地决定什么都不做。

请注意,如果 parent 进程(称之为 Program1)派生了一些 child 处理然后使用 exec*() 将其自身替换为另一个程序 Program2Program2 不知道它的进程是其他 children 的 parent 进程,而不是它创建的。这合理吗?是的,可以做到;我有测试代码可以做到这一点。有可能吗?不;它需要一个不寻常的设置,但并不难做到。例如,如果 shell 脚本启动了一些后台进程,然后发出 exec program-that-forks,派生程序的进程具有 shell 创建的后台进程 children ,即使分叉的程序没有创建这些进程。