2013-06-22 68 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),并将其附加到事件循环中。在这种情况下,您仍然需要如上所示屏蔽信号。