如何使用signal(3)为正在运行的操作系统上可用的ALL信号注册信号处理程序?
我的代码如下所示:
void sig_handler(int signum)
{
printf("Received signal %d\n", signum);
}
int main()
{
signal(ALL_SIGNALS_??, sig_handler);
while (1) {
sleep(1);
};
return 0;
}
答案 0 :(得分:5)
大多数系统在NSIG
中定义了一个宏_NSIG
或signal.h
(前者在标准一致性模式中不可用,因为它违反了命名空间),因此循环{{ 1}}将走所有信号。此外,在具有信号掩码的POSIX系统上,for (i=1; i<_NSIG; i++)
是信号数量的上限,如果未定义CHAR_BIT*sizeof(sigset_t)
和NSIG
,则可以将其用作回退。
答案 1 :(得分:3)
信号处理程序必须处理重入问题和其他问题。在实践中,屏蔽信号然后不时地检索信号通常更方便。您可以使用以下功能屏蔽所有信号(SIGSTOP
和SIGKILL
除外,您无法处理):
sigset_t all_signals;
sigfillset(&all_signals);
sigprocmask(SIG_BLOCK, &all_signals, NULL);
如果你正在使用pthreads,代码会略有不同。在创建任何其他线程之前,或者(最好)在主线程中调用它:
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);
如果有待处理的信号,有关该信号的信息将放在result
中,rc
将是信号编号;如果不是,rc
将为-1,errno
将为EAGAIN
。如果您已经调用select(2)
/ poll(2)
(例如,作为某些事件驱动系统的一部分),您可能需要创建一个signalfd(2)
并将其附加到您的事件循环中。在这种情况下,您仍然需要屏蔽信号,如上所示。