如何跟踪wait()和fork()命令

时间:2013-11-11 23:11:36

标签: c fork

我很难理解子进程如何以及何时返回父进程。看看我使用各种网站放在一起的这个例子:

#include <stdio.h>
#include <stdlib.h>

main( int argc, char *argv[] )
{
   int i;
   int pid;
   int wpid;
   int status;

   time1.tv_sec = 5L;
   time1.tv_nsec = 0L;

   for ( i = 0; i < 10; i++ )
   {
      pid = fork();

      if ( pid < 0 ) {
         printf ( "Error" );
         exit ( 1 );
      }
      else if ( pid  == 0 ) {
         break;
      }
   }

   while ( ( wpid = wait ( &status ) ) > 0 )
   {
      printf ( "Exit status of %d was %d (%s)\n", ( int ) wpid, status, ( status == 0 ) ? "accept" : "reject" );
   }

   return 0;
}

我不明白孩子到底是什么回归,何时何地?在fork命令之后,子进入第二个循环,但是它永远不会退出该循环以进一步向下并到达返回命令。我应该放一个条件,所以只有父进行那个循环?孩子是否忽略wait()命令?

我发现这是一个经验丰富的程序员对我这样的人来说不够愚蠢的问题。我找不到解决这个问题的单一答案。

4 个答案:

答案 0 :(得分:3)

wait收到进程的退出代码,即int。例如,可以通过exit(1)

设置该值

您的代码如下所示

time1.tv_nsec = 0L; // only "parent" thread here.

for ( i = 0; i < 10; i++ )
{
  pid = fork();  // create a child.

  if ( pid < 0 ) {   //
     printf ( "Error" );
     exit ( 1 );
  }
  else if ( pid  == 0 ) { // only the child will enter this if, so it will exit the loop.
     break;
  }
}

 while ( ( wpid = wait ( &status ) ) > 0 )  // children and parent run this condition, but the
                                            // children don't have children so they will just
                                            // exit the wait function with -1, so they don't run
                                            // loop
 {
    printf ( "Exit status of %d was %d (%s)\n", ( int ) wpid, status, ( status == 0 ) ? "accept" : "reject" );  // only the parent executes this
 }

 return 0;   // return from main, this value is the one that will be received by the wait (in case
             // of children processes. There is also the option of using exit(0); exit ends program
             // execution everywhere it is used.

答案 1 :(得分:2)

当您致电fork时,子流程父流程从同一个地方开始:在调用fork之后。唯一的区别是,fork为子进程返回0,子进程的PID(> 0)返回到父进程。这就是为什么在调用fork之后你需要一个有条件的权利。

因此,在您的子进程中,它将检查返回值0和break,它将进入while循环。父进程将保留在for循环中,它将继续分支子进程,直到它完成为止。然后它将进入while循环。

在您的子进程中,wait()函数可能正在返回ECHILD(请参阅the man page)因为没有子进程,所以您应该确保子线程没有调用它或确保他们优雅地处理错误。

答案 2 :(得分:1)

好吧,让我们来看看fork()的工作原理。

调用fork时,通过克隆调用它的进程创建一个新进程。此过程(从现在开始孩子)是第一个(进程)的完全副本。这意味着两个进程将继续执行fork()之后的命令。

现在,您如何区分哪一个是父母,哪一个是孩子?基于fork()的返回状态。

  

成功完成后,fork()将向子进程返回0   并应将子进程的进程ID返回给父进程   过程

因此,如果我们假设一切正常并且没有发生错误,则代码的break;语句将在子进程中执行,并且父进程将继续生成子进程,直到循环结束。

现在,在break;每个孩子发现自己wait之后。来自wait()的联机帮助页:

  

等待,waitpid - 等待子进程停止或终止

但等一下!每个子进程都没有孩子等待!因此wait()ECHILD失败并且孩子们终止。

此外,在执行所有循环迭代后,父进程将找到自己wait。父进程有几个子进程,并在它们终止时获取它们的退出状态。孩子不会以任何特定的顺序终止,这取决于操作系统,你不能假设一个人会在另一个人之前终止。

我希望上面的内容能够澄清并且现在能够修复您的代码以使其正常工作。

问候。

答案 3 :(得分:0)

是的,您需要提供条件逻辑,以指导子进程的工作。由于fork将设置父级的堆栈变量而不是子级的堆栈值,因此您可以执行以下操作:

 pid_t pid1 = 0;

 printf("*** Parent is about to fork process 1 ***\n");
 if ((pid1 = fork()) < 0) {
      printf("Failed to fork process 1\n");
      exit(1);
 }
 else if (pid1 == 0)
 {
      // Work of the child process
 }
 else 
 {
      // Work of the parent process
 }
相关问题