2010-04-25 118 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