【问题标题】:C - Processes in linux handle with any signalC - linux中的进程处理任何信号
【发布时间】:2015-12-31 00:23:35
【问题描述】:

我正在编写具有必须处理我给他的任何信号的进程的代码。我读到我应该做这样的事情

void signalHandler(int sig_num)
{
    // some stuff
}

//My process
int i;
for (i = 1; i <= 64; i++)
     signal(i, signalHandler);

这是正确的解决方案吗??

【问题讨论】:

  • 如果不知道您要解决什么问题,就很难知道解决方案是否正确。
  • 这个直接问题的直接答案是“否”。
  • 我的进程必须处理我发送的任何信号。因此,如果我发送了例如 SIGINT 或其他一个,它应该为这个信号起作用。我不想为所有信号写 signal(..., signalHandler) 所以我想知道如何使它通用。
  • 你的代码是否知道它正在处理什么信号?
  • 我的程序可以获得 64 个信号中的一个,我希望所有这些信号都有一个功能。

标签: c linux process signals


【解决方案1】:

虽然@Dylan 的解决方案看起来不错,但它提出了一个常见问题,那就是与signal 函数的兼容性问题。因此建议您始终使用sigaction。这是一个例子

#include <stdio.h>
#include <signal.h>

static void handler(int signo){
   write(stdout, &signo, sizeof(int));
}

int main() {
   struct sigaction sa;
   sa.sa_handler = handler;
   int i;
   for (i = 1; i <= 64; i++) {
        sigaction(i, &sa, NULL);
   }
   while(1);
  return 0;
}
  1. 尽量避免使用signal
  2. 切勿在信号处理程序中使用任何不是 Reentrant 或不是 Async-signal-safe 函数的函数,例如 printf

检查来自here的信号处理程序中允许的函数列表

POSIX.1-2004(也称为 POSIX.1-2001 技术勘误 2) 需要一个实现来保证以下功能 可以在信号处理程序中安全地调用:

【讨论】:

  • 你能多说一下为什么我们应该避免使用信号功能吗?使用此功能我们会遇到什么问题?
  • signal 函数存在可移植性问题,在少数 BSD 系统中,它需要单独的卸载程序..谷歌你会找到足够的信息。
  • 谢谢。顺便说一句,这是非常有趣的解决方案:)
  • 我发现在以前的操作系统中的信号函数中,signalHandler 必须返回 int 但现在它可以返回 void。
  • 其实int值可以用来表示之前信号处理的地址。也可以留空。
【解决方案2】:

如果您想使用相同的信号处理程序来处理信号 1 到 64,那么您就在正确的轨道上。该测试程序将通过打印信号编号来处理信号 1 到 64。

#include <stdio.h>
#include <signal.h>

void signalHandler(int sig_num)
{
    printf("Signal %d caught!\n", sig_num);
}

int main(int argc, char const *argv[])
{
    //My process
    int i;
    for (i = 1; i <= 64; i++) {
        signal(i, signalHandler);
    }

    while (1);
    return 0;
}

例如,当您在此程序运行时按 CTRL+C。内核向程序发送信号 2 SIGINT,并调用 signalHandler(2)。该程序打印“信号 2 被捕获!”

Facepalm 后编辑:这个程序显然需要用kill -9 命令终止........

【讨论】:

  • 可以告诉我这是如何工作的,因为我想了解为什么它会在任何时候读取我们的信号。或者 for() 应该在不定式循环中??
  • 对于 * 评论来说,解释信号有点过于深入,但请查看一些在线资源,例如 linux.die.net/man/2/signal。基本上,signal(i, signalHandler) 告诉内核在信号i 被捕获时调用signalHandler。对于 i=1、i=2、... i=63、i=64,您调用 signal(i, signalHandler)。所以信号1-64触发signalHandler函数
  • 我知道函数 signal() 是如何工作的,但我想了解我们为什么要使用 for() 循环。对我来说应该是:64 次执行函数信号(),然后执行不定式循环 while(1)。或者只有当我们向这个进程发送信号时才会做出反应?
  • 在理解问题时遇到了一些困难。 for 循环调用signal 64 次。无限的while循环使程序永远循环。