2011-12-07 47 views
1

我看到這樣的SIGCHLD處理器的一些例子:SIGCHLD處理程序重新安裝

void child()                             
{                              
    wait(0);                           
    signal(SIGCHLD, child);  
} 
void server_main() 
{ 
    ... 
    signal(SIGCHLD, child); 
    ... 
    for(;;;) { 
     ... 
     switch(fork()) { 
     ... 
     } 
    } 

有兩個部分在混淆我的處理程序: 1)。當孩子終止或停止時,SIGCHLD被捕獲。那麼爲什麼需要在處理程序中調用wait?信號已經到達。 2)。爲什麼需要重新安裝SIGCHLD處理程序。信號調用是否會一勞永逸地安裝處理程序?

謝謝!

回答

2
  1. 當子進程執行完畢 時,會觸發SIGCHLD。但它仍然會在進程表中(作爲所謂的殭屍進程的一個 ),以便讓父級獲取子級的退出 值。調用wait()將清除該子進程的進程表 。
  2. 如果您只創建n子進程,那麼當所有子進程都死亡時,信號處理程序仍然沒有到位。

我建議你看看sigaction來代替,因爲signal的行爲因Unix而異。

+0

謝謝,我看到了第一點。對於第二個,信號處理程序是爲父權安裝的?爲什麼當多個子進程死亡可能會導致信號處理程序不起作用? – Oxdeadbeef

+0

請看看sarnold的解釋,他解釋得相當不錯。 – halfdan

1

是不是信號調用會一次性安裝處理程序?

你不能依賴這種行爲;也許信號處理程序將被清除,也許它會持續。這是歷史信號處理問題的一部分。該signal(3)手冊頁對我的系統報告:

When a signal occurs, and func points to a function, it is 
    implementation-defined whether the equivalent of a: 


      signal(sig, SIG_DFL); 

    is executed or the implementation prevents some 
    implementation-defined set of signals (at least including 
    sig) from occurring until the current signal handling has 
    completed. 

不可靠的信號已經在SysVr4引入標準化,POSIX.1-2001 sigaction(2)基於信號被更換近:

struct sigaction { 
     void  (*sa_handler)(int); 
     void  (*sa_sigaction)(int, siginfo_t *, void *); 
     sigset_t sa_mask; 
     int  sa_flags; 
     void  (*sa_restorer)(void); 
    }; 

    int sigaction(int signum, const struct sigaction *act, 
       struct sigaction *oldact); 

這是可悲的是更復雜來編寫代碼,但是一旦編寫完代碼,您就不必擔心是否需要重新安裝處理程序 - 而且您不必擔心信號在處理信號時第二次到達。

相關問題