2010-04-25 49 views
27

我需要使用fork()和wait()函数来完成一个赋值。我们正在建模非确定性行为,并且如果存在多个可能的转换,则需要fork()程序。有两个子进程fork()和wait()

为了试着弄清楚fork和wait的工作方式,我刚做了一个简单的程序。我想现在我明白了这些调用是如何工作的,如果程序只分支一次,那么它会很好,因为父进程可以使用单个子进程的退出状态来确定子进程是否达到接受状态。

正如您从后面的代码中看到的,我希望能够处理必须有多个子进程的情况。我的问题是,你似乎只能使用_exit函数设置一次状态。因此,正如在我的示例中,父进程测试的退出状态显示第一个子进程发出0,因为它是退出状态,但没有关于第二个子进程的信息。

我试着简单地不_exit() - 拒绝,但是那个子进程将继续,实际上似乎有两个父进程。

对不起华夫饼,但我会很感激,如果有人能告诉我我的父母过程如何获得多个子过程的状态信息,或者我会很高兴父过程只注意到接受状态子进程,但在这种情况下,我将成功地需要退出具有拒绝状态的子进程。

我的测试代码如下:

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

int main(void) { 

    pid_t child_pid, wpid, pid; 
    int status = 0; 
    int i; 

    int a[3] = {1, 2, 1}; 
    for(i = 1; i < 3; i++) { 
     printf("i = %d\n", i); 
     pid = getpid(); 
     printf("pid after i = %d\n", pid); 
     if((child_pid = fork()) == 0) { 
      printf("In child process\n"); 
      pid = getpid(); 
      printf("pid in child process is %d\n", pid); 
      /* Is a child process */ 
      if(a[i] < 2) { 
       printf("Should be accept\n"); 
       _exit(1); 
      } else { 
       printf("Should be reject\n"); 
       _exit(0); 
      } 
     } 
    } 

    if(child_pid > 0) { 
     /* Is the parent process */ 
     pid = getpid(); 
     printf("parent_pid = %d\n", pid); 
     wpid = wait(&status); 
     if(wpid != -1) { 
      printf("Child's exit status was %d\n", status); 
      if(status > 0) { 
       printf("Accept\n"); 
      } else { 
       printf("Complete parent process\n"); 
       if(a[0] < 2) { 
        printf("Accept\n"); 
       } else { 
        printf("Reject\n"); 
       } 
      } 
     } 
    } 
    return 0; 
} 

回答

35

它在我看来,好像基本问题是你有一个wait()调用,而不是一个等待,直到没有更多的孩子的循环。如果最后的fork()成功,您也只能等待,而不是至少有一个fork()成功。

如果您不想要正常的清理操作(如冲洗打开的文件流,包括stdout),则应该只使用_exit()。有时候使用_exit();这不是其中的一个。 (在这个例子中,你当然也可以直接让孩子回来,而不是直接调用exit(),因为从main()返回等于退出返回状态。但是,大多数情况下你会在功能比其他0​​,然后exit()往往是适当的。)


黑客攻击,你的代码的简化版本,给我想要的诊断。请注意,您的for循环跳过了数组的第一个元素(我的不是)。

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

int main(void) 
{ 
    pid_t child_pid, wpid; 
    int status = 0; 
    int i; 
    int a[3] = {1, 2, 1}; 

    printf("parent_pid = %d\n", getpid()); 
    for (i = 0; i < 3; i++) 
    { 
     printf("i = %d\n", i); 
     if ((child_pid = fork()) == 0) 
     { 
      printf("In child process (pid = %d)\n", getpid()); 
      if (a[i] < 2) 
      { 
       printf("Should be accept\n"); 
       exit(1); 
      } 
      else 
      { 
       printf("Should be reject\n"); 
       exit(0); 
      } 
      /*NOTREACHED*/ 
     } 
    } 

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

示例输出(MacOS X 10.6。3):

parent_pid = 15820 
i = 0 
i = 1 
In child process (pid = 15821) 
Should be accept 
i = 2 
In child process (pid = 15822) 
Should be reject 
In child process (pid = 15823) 
Should be accept 
Exit status of 15823 was 256 (accept) 
Exit status of 15822 was 0 (reject) 
Exit status of 15821 was 256 (accept) 
+0

好的。我明白。非常感谢您的回复。 – Joe 2010-04-25 14:28:10

+0

再次感谢您的时间。那很棒。我在你的第一篇文章后制作了自己的工作版本,但你的版本更加简洁。欢呼 – Joe 2010-04-25 14:48:17

+0

@Joe如果这个回应对你最有帮助,那么你应该通过点击左边的复选标记来接受它。 – 2010-04-25 14:50:31

8

把你的等待()函数在一个循环中,等待所有的子进程。如果没有更多子进程可用,则wait函数将返回-1,并且errno将等于ECHILD。

+0

大。我明白。非常感谢。 – Joe 2010-04-25 14:27:25

1

光辉典范乔纳森·莱弗勒,使在SLES你的代码的工作,我需要添加一个额外的头,让将为pid_t对象:)

#include <sys/types.h> 
+0

这很奇怪...... POSIX 2008和我遇到的所有其他Linux系统都不需要''标头。在''中有函数(如'getpid()')需要声明中的类型,所以''不需要明确包含。你能说出你使用的编译器选项吗?#include '? – 2013-02-10 13:00:40

+0

@JonathanLeffler我知道这是一个旧评论,但SLES比其他人要老。这就像RedHat的EL。所以这就是我猜测的原因。 – Shiki 2013-05-13 11:54:08