2017-10-01 51 views
0

我試過使用下面的(Will wait and waitpid block SIGCHLD and unblock it when they return in Linux?)來回答我的問題。鏈接的解決方案讓我瞭解下面的內容。那麼爲什麼它錯了?在waitpid中處理SIG_CHLD


考慮以下幾點:

  • 的處理器

    void sig_child(int sig) 
    { 
    signal(SIGCHLD, sig_child); 
    
    if (sig == SIGCHLD) 
    { 
        int status; 
        pid_t num; 
        while ((num = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) 
        { 
    
        } 
        if (num == -1 && errno != ECHILD) 
        { 
         // We shouldn't reach here 
         assert(0); 
        } 
    
    } 
    

主要導語:

  if (pidnum) 
      { //Some work 
       int status; 
       pid_t num = waitpid(pidnum, &status, 0); 
       // Some work 
      } 

我認爲,以下應該發生:

1)主代碼(在第二導語)調用waitpid函數

2)SIG_CHLD升高,從而控制轉移到信號處理程序

3)信號處理程序從信號處理程序中刪除終止的子程序,獲取其狀態信息

4)當控制轉回到主代碼(第二Blurb的),因爲該進程的孩子已經從進程表中刪除,NUM應設置爲-1


其實中,發生如下(我使用的是現在去除追查流量一些打印語句),上述矛盾我的理解:

1)主要的Blurb達到waitpid函數

2)SIG_CHLD升高,從而控制轉移給處理者

3)NUM被設置爲-1,並將errno到ECHILD

4),控制返回到主書籍說明,其中num給出 子已被前叉形的PID。

+0

你能解釋一下你最終要達到什麼目的?你爲什麼要調用'waitpid'兩次? –

+0

我想編程一個迷你shell,我可以設置後臺進程和前臺進程。我在主界面中調用了waitpid,沒有WNOHANG,因爲我希望我的shell等到其子進程結束。還有另一部分主界面(未顯示),其中我產生了後臺進程。這些由信號處理程序處理。我通過與WNOHANG等待來處理這些後臺進程,這樣如果多個後臺進程在同一時間終止,我可以收穫所有後臺進程。 – Muno

回答

0

你做兩waitpid重疊的標準,並抱怨說,一個映入你的過程中,另一種則不是,而不是周圍的其他方式。我不認爲有什麼辦法可以解決這個特殊情況。

我看到它的方式,有兩條途徑可以找到解決方案。一種是使用不重疊的標準。問題在於,看到如何創建這種情況並不容易。

更合理的解決方案是隻有一個waitpid在主循環。請等待檢查報告的pid,並以兩種不同的方式處理它。如果它是主程序的孩子,那麼做一件事。如果它是您正在運行的後臺任務之一,則執行另一個(或者,在您的情況下,不做任何事情)。

如果您不能在任何情況下處理後臺進程的退出,而不是在主循環內部,那麼在您進行主等待時阻止SIGCHLD

在任何情況下,始終牢記SIGCHLD是非排隊信號。這意味着您永遠無法保證您的信號處理程序被調用的次數與您運行的wait的次數之間存在1:1的關係。