【问题标题】:Signal handler for all signal所有信号的信号处理程序
【发布时间】:2013-06-19 19:06:03
【问题描述】:

如何使用 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;
}

【问题讨论】:

  • for循环中,从1到31?
  • 每个系统都有一个信号列表。请参阅/usr/include/signal.h 没有一个标准宏可以用来表示所有这些宏。加。你不能把他们都困住,例如SIGKILL
  • 那么你应该检查你是哪个平台......但我认为你不需要它们,SIGINT、SIGUSR1/2 和更多应该足够了。顺便提一句。在 /usr/include/bits/signum.h 你可以找到所有的描述。
  • 您不能在信号处理程序中使用 printf()。 (它是不可重入的)
  • @R 如果在信号处理程序中执行 printf 时信号到达会发生什么? (提示:坏事)在信号处理程序中调用 printf 是不安全的,即使在这个简单的程序中也是如此。

标签: c linux unix signal-handling


【解决方案1】:

大多数系统在signal.h 中定义了一个宏NSIG_NSIG(前者在标准一致性模式下不可用,因为它违反了命名空间),这样循环for (i=1; i<_NSIG; i++) 将遍历所有信号。此外,在具有信号掩码的 POSIX 系统上,CHAR_BIT*sizeof(sigset_t) 是信号数量的上限,如果 NSIG_NSIG 均未定义,您可以将其用作后备。

【讨论】:

  • 但我不明白为什么不是i = 0 而是i = 1。根据上面链接中的解释,NSIG 的值既对应于定义的信号数,也对应于<largest signal number> + 1,这意味着信号号以0 开头。我怀疑你的代码是故意的,所以你能给我一个解释吗? (也许What does kill -0 do? 是相关的?)
【解决方案2】:

信号处理程序必须处理重入问题和其他问题。在实践中,屏蔽信号然后不时检索它们通常更方便。您可以使用以下命令屏蔽所有信号(SIGSTOPSIGKILL 除外,它们无论如何都无法处理):

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

如果您使用 pthread,代码会略有不同。在创建任何其他线程之前,在每个线程或(最好)在主线程中调用它:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 2017-11-13
    • 1970-01-01
    • 2013-12-21
    相关资源
    最近更新 更多