2013-06-22 122 views
4

如何使用信號(3)在運行的操作系統上爲所有信號註冊信號處理程序?所有信號的信號處理程序

我的代碼如下所示:

void sig_handler(int signum) 
{ 
    printf("Received signal %d\n", signum); 
} 


int main() 
{ 
    signal(ALL_SIGNALS_??, sig_handler); 
    while (1) { 
     sleep(1); 
    }; 
    return 0; 
} 
+3

在'for'循環中,從1到31? –

+4

每個系統都有一個信號列表。參見'/ usr/include/signal.h'沒有一個標準的宏可以用來表示所有的宏。加。例如,你不能捕獲所有的「SIGKILL」。 –

+0

是的,我已經提到過。但是在一些現代操作系統上有超過32個。例如,在FreeBSD上kill -l會返回126個條目。 – kober

回答

5

多數系統有一個宏觀NSIG_NSIGsignal.h這樣一個循環定義(前者不會在標準一致性模式可用,因爲它違反了命名空間) for (i=1; i<_NSIG; i++)將走所有信號。此外,在具有信號掩碼的POSIX系統上,如果既不定義NSIG也不定義_NSIGCHAR_BIT*sizeof(sigset_t)是可用作後退的信號數量的上限。

3

信號處理程序必須處理重入問題和其他問題。在實踐中,屏蔽信號然後不時檢索它們通常更方便。您可以使用此屏蔽所有信號(除了SIGSTOPSIGKILL,你不能無論如何處理):

sigset_t all_signals; 
sigfillset(&all_signals); 
sigprocmask(SIG_BLOCK, &all_signals, NULL); 

代碼略有不同,如果你使用的並行線程。

sigset_t all_signals; 
sigfillset(&all_signals); 
pthread_sigmask(SIG_BLOCK, &all_signals, NULL); 

一旦你這樣做,你應該定期調用sigtimedwait(2)這樣的:

struct timespec no_time = {0, 0}; 
siginfo_t result; 
int rc = sigtimedwait(&all_signals, &result, &no_time); 

如果您創建的任何其他人之前在每一個線程在主線程中調用該方法,或(最好)有一個待處理的信號,關於它的信息將被放在resultrc之間的信號編號;如果不是,則rc將是-1並且errno將是EAGAIN。如果您已撥打select(2)/poll(2)(例如,作爲某些事件驅動系統的一部分),則可能需要創建signalfd(2),並將其附加到事件循環中。在這種情況下,您仍然需要如上所示屏蔽信號。