【问题标题】:Using sigaction(), c使用 sigaction(), c
【发布时间】:2012-07-13 06:19:24
【问题描述】:

我正在阅读有关sigaction() 的一些信息(来源来自我的课程笔记),但我不确定我是否理解这段文字:

信号掩码仅在以下期间计算和安装 信号处理程序。

默认情况下,信号“sig”出现时也会被屏蔽。

一旦使用 sigaction 为特定信号安装了操作, 在明确请求另一个操作之前,它会一直保持安装状态。

这是否意味着从信号处理程序返回后恢复默认信号掩码? 另外,使用后是否必须重新安装处理程序,就像我使用signal()一样?

另外,还有这段代码:

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

void termination_handler(int signum) {
    exit(7);
}

int main (void) {
  struct sigaction new_action,old_action;
  new_action.sa_handler = termination_handler;
  sigemptyset(&new_action.sa_mask);
  sigaddset(&new_action.sa_mask, SIGTERM);
  new_action.sa_flags = 0;
  sigaction(SIGINT, NULL, &old_action);
  if (old_action.sa_handler != SIG_IGN) {
         sigaction(SIGINT,&new_action,NULL);
  }
  sleep(10);
  return 0;
}

那么 - SIGTERM 究竟将如何处理?我可以看到安装的处理程序是termination handler(),但随后SIGTERM 被添加到信号掩码中而没有使用sigprocmask()。这是什么意思?谢谢!

附:最后一个问题:为什么main() 中有if 语句?

【问题讨论】:

  • 你用过自己的信号处理器吗?如果没有,我的建议是首先使用您自己的信号处理程序。那么,sigaction 就很容易理解了。 İf 语句用于比较(检查捕获的信号应为一个)。而且,第一个问题的答案在于“信号处理程序的持续时间”。

标签: c unix signals bitmask systems-programming


【解决方案1】:

让我们尝试了解修改后的代码版本发生了什么:

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

void termination_handler(int signum)
{
    printf("Hello from handler\n");
    sleep(1);
}

int main (void)
{
    //Structs that will describe the old action and the new action
    //associated to the SIGINT signal (Ctrl+c from keyboard).
    struct sigaction new_action, old_action;

    //Set the handler in the new_action struct
    new_action.sa_handler = termination_handler;
    //Set to empty the sa_mask. It means that no signal is blocked
    // while the handler run.
    sigemptyset(&new_action.sa_mask);
    //Block the SEGTERM signal.
    // It means that while the handler run, the SIGTERM signal is ignored
    sigaddset(&new_action.sa_mask, SIGTERM);
    //Remove any flag from sa_flag. See documentation for flags allowed
    new_action.sa_flags = 0;

    //Read the old signal associated to SIGINT (keyboard, see signal(7))
    sigaction(SIGINT, NULL, &old_action);

    //If the old handler wasn't SIG_IGN (it's a handler that just
    // "ignore" the signal)
    if (old_action.sa_handler != SIG_IGN)
    {
        //Replace the signal handler of SIGINT with the one described by new_action
        sigaction(SIGINT,&new_action,NULL);
    }

    while(1)
    {
        printf("In the loop\n");
        sleep(100);
    }
    return 0;
}

因此,如果您编译并启动它,然后按 Ctrl+C,那么您将执行处理程序消息,然后您会立即从主程序的睡眠中返回。您可以根据需要执行多次,但仍会显示处理程序消息和内循环消息。

所以,你给一个函数,然后 sigaction 做所有需要的事情,把信号和你的处理程序挂钩。


现在,sigterm 呢?如果您在终止处理程序中增加睡眠时间,您可以在按 Ctrl+C 后键入类似“pkill --signal SIGTERM ./a.out”的内容。那么,会发生什么?没有! SIGTERM 信号在终止处理程序运行时被阻塞。但是一旦你回到主,现在 SIGTERM 将终止应用程序。

(请记住,在测试此代码时,您仍然可以通过发送 SIGKILL 信号来终止应用程序。)


如果您想了解更多信息,并在信号方面获得更多乐趣,您可以使用 signal manualsigaction manual 来了解更多信息。请注意,您还有 sigaction 结构的详细说明。

【讨论】:

    猜你喜欢
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多