2014-03-27 18 views
0

我什麼時候需要使用waitpid函數,如果我使用的是execl的子進程可能需要一段時間才能完成?waitpid與execl用於兒童返回-1與ECHILD?

當我在父親中使用waitpid時,它給了我一個孩子,因爲waitpid的返回值是0.我嘗試在另一個函數中使用waitpid,在那裏它返回-1和ECHILD。如果我不確定天氣小孩是否完工,我應該何時使用waitpid?

//pid_t Checksum_pid = fork(); 
Checksum_pid = fork(); 

if (Checksum_pid == 0) 
{ 
    execl(path, name, argument as needed, ,NULL); 
    exit(EXIT_SUCCESS);  
} 
else if (Checksum_pid > 0) 
{ 
    pid_t returnValue = waitpid(Checksum_pid, &childStatus, WNOHANG); 

    if (returnValue > 0) 
    { 
     if (WIFEXITED(childStatus)) 
     { 
      printf("Exit Code: _ WEXITSTATUS(childStatus)") ;    
     } 
    } 
    else if (returnValue == 0) 
    { 
     //Send positive response with routine status running (0x03) 
     printf("Child process still running") ; 
    } 
    else 
    { 
     if (errno == ECHILD) 
     { 
      printf(" Error ECHILD!!") ; 
     } 
     else if (errno == EINTR) 
     { 
      // other real errors handled here. 
      printf(" Error EINTR!!") ; 
     } 
     else 
     { 
      printf("Error EINVAL!!") ; 
     }  
    } 
} 
else 
{ 
    /* Fork failed. */ 
    printf("Fork Failed") ; 
} 
+1

的'出口(EXIT_SUCCESS);''的EXECL()'是錯誤的指示符之後;如果'execl()'返回,它失敗了,所以你應該使用'exit(EXIT_FAILURE)'退出,讓父進程知道你失敗了。 –

+0

當我嘗試在execl和execl以下的子進程中使用printf時。我無法得到任何印花......我不知道爲什麼。我想上面execl我應該得到印刷品。我寫信嗎?如果execl成功,那麼如何退出子進程來終止它呢?如果我在父進程中使用waitpid(在某些執行後的其他函數中的某處),那麼使用waitpid與在父進程中獲得的第一個參數相同的childpid是否有效? – kapilddit

回答

2

如果用WNOHANG等待,那麼你不會得到任何有用的狀態,除非你的孩子已經死了 - 它甚至可能沒有竟能但(它仍然可以等待可執行代碼被加載從母盤執行waitpid()時)。

如果您想知道孩子已經完成,請不要使用WNOHANG - 使用0作爲第三個參數,除非您想了解未經過跟蹤或繼續的過程。這將等到通過Checksum_pid退出標識的過程,或者系統通過某種神祕的方式(這是我從來沒有過這種情況)失去它的軌道。


這段代碼產生Exit Code: 0作爲輸出:

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

int main(void) 
{ 
    pid_t Checksum_pid = fork(); 

    if (Checksum_pid < 0) 
     printf("Fork Failed\n"); 
    else if (Checksum_pid == 0) 
    { 
     execl("/bin/sleep", "/bin/sleep", "2", NULL); 
     exit(EXIT_FAILURE); 
    } 
    else 
    { 
     int childStatus; 
     pid_t returnValue = waitpid(Checksum_pid, &childStatus, 0); 

     if (returnValue > 0) 
     { 
      if (WIFEXITED(childStatus)) 
       printf("Exit Code: %d\n", WEXITSTATUS(childStatus)); 
      else 
       printf("Exit Status: 0x%.4X\n", childStatus); 
     } 
     else if (returnValue == 0) 
      printf("Child process still running\n"); 
     else 
     { 
      if (errno == ECHILD) 
       printf(" Error ECHILD!!\n"); 
      else if (errno == EINTR) 
       printf(" Error EINTR!!\n"); 
      else 
       printf("Error EINVAL!!\n"); 
     } 
    } 

    return 0; 
} 

這是非常相似的代碼;我只是將fork()的支票移到頂端。我仍然希望擺脫if陳述的「叢林樹木」,但它並不重要。當你運行這段代碼時會發生什麼?你有什麼改變來獲得ECHILD錯誤(你可以改變它,讓你得到的ECHILD錯誤)?

當你設法讓基於斷碼此重現該問題,我們就可以明白爲什麼你這種行爲。

在Mac OS X 10.9.2上測試使用GCC 4.8.2的Mavericks,以及使用GCC 4.8.1的Ubuntu 13.10(我需要添加-D_XOPEN_SOURCE=700才能使用我的嚴格編譯標誌進行編譯; Mac OS X無需管理),但我不希望在其他地方得到不同的結果。

+0

然後我需要使用什麼?什麼意思如果我把0作爲可選的第三個參數而不是WNOHANG? – kapilddit

+0

我需要在waitpid中使用什麼參數?我嘗試過WCONTINUED,但沒有成功。我可以使用WUNTRACED嗎? – kapilddit

+0

查看更新以回答;使用'0'。 –

0
int start(int Area) 
{ 

     int childStatus; 
     pid_t Checksum_pid = fork(); 

     if(Checksum_pid < 0) 
     { 
      /* Fork failed. */ 
      printf(" Fork Failed") ; 

     } 
     else if (Checksum_pid == 0)   
     { 

      for (int i = 0; i<5; i++) 

      { 

       if (g_area[i] == Area) 
       { 

        execl(ScriptPath, ScriptName, NULL); 

       } 
      } 

      exit(EXIT_FAILURE); 

     } 

     else   
     { 
      /* This is the parent process. */   
      pid_t returnValue = waitpid(Checksum_pid, &childStatus, 0); 


      if (returnValue > 0) 
      { 
       // Check if child ended normally 
       printf("WAITPID Successful") ;     

       if (WIFEXITED(childStatus)) 
       { 
      printf("Exit Code: _ WEXITSTATUS(childStatus)"); 
       } 

      } 

      else if (returnValue == 0) 
      { 

       printf("Child process still running") ; 

      } 
      else 
      { 

       if (errno == ECHILD) 
       { 
        printf("Error ECHILD!!") ; 
       } 
       else if (errno == EINTR) 
       { 
        printf("Error EINTR!!") ; 
       } 
       else 
       { 
        printf(" Error EINVAL!!") ; 
       }  
       retCode = FAILED; 
      }   

     }    
} 
+0

我用上面的代碼&得到「錯誤ECHILD !!」作爲輸出... – kapilddit

+1

請研究如何創建一個MCVE [如何創建一個最小,完整和可驗證的示例?](http://stackoverflow.com/help/mcve)或 SSCCE([Short,Self-Contained ,正確的例子](http://sscce.org/)),兩個名稱爲相同的基本思想。在上面的代碼中,什麼是'g_area'? 'ScriptPath'和'ScriptName'的價值是什麼?你通過什麼'Area'的價值?爲什麼沒有任何消息以換行符結束(直到他們這樣做纔會可靠地顯示)。爲什麼代碼中有這麼多空行?爲什麼不打印WEXITSTATUS值,而不是在輸出中包含宏名稱? –

+0

該問題已通過刪除OSAL中的SIGCHLD處理程序得以解決。 – kapilddit

4

如果信號SIGCHLD被忽略(這是默認的),你跳過WNOHANG由喬納森提到,waitpid函數將掛起,直到孩子退出,然後失敗,代碼ECHILD。我自己在父進程只需要等待子進程結束的情況下遇到了這種情況,爲SIGCHLD註冊一個處理程序似乎有點矯枉過正。自然跟進的問題是「是否是確定治療的ECHILD在這種情況下,可以預期的事件,還是我總是應該寫SIGCHLD處理程序?」, 但我不知道答案。

documentation for waitpid(2)

ECHILD

(for waitpid() or waitid()) The process specified by pid (waitpid()) or idtype and id (waitid()) does not exist or is not a child of the calling process. (This can happen for one's own child if the action for SIGCHLD is set to SIG_IGN. See also the Linux Notes section about threads.)

進一步回落

POSIX.1-2001 specifies that if the disposition of SIGCHLD is set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD (see sigaction(2)), then children that terminate do not become zombies and a call to wait() or waitpid() will block until all children have terminated, and then fail with errno set to ECHILD. (The original POSIX standard left the behavior of setting SIGCHLD to SIG_IGN unspecified. Note that even though the default disposition of SIGCHLD is "ignore", explicitly setting the disposition to SIG_IGN results in different treatment of zombie process children.) Linux 2.6 conforms to this specification. However, Linux 2.4 (and earlier) does not: if a wait() or waitpid() call is made while SIGCHLD is being ignored, the call behaves just as though SIGCHLD were not being ignored, that is, the call blocks until the next child terminates and then returns the process ID and status of that child.

this answer見。