【问题标题】:signal handling in linux for clinux for c 中的信号处理
【发布时间】:2015-08-22 12:43:49
【问题描述】:

我试图通过我在网上找到的示例程序了解信号在 Linux 中的工作原理,但它有一些我不太了解的部分。

这是我的示例程序:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

void catcher(int sig) {
    printf("catcher() has gained control\n");
}

int main(int argc, char *argv[]) {
    struct sigaction sigact;
    sigset_t sigset;

    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigact.sa_handler = catcher;
    sigaction(SIGUSR1, &sigact, NULL);

    printf("before first kill()\n");
    kill(getpid(), SIGUSR1);

    sigemptyset(&sigset);
    sigaddset(&sigset, SIGUSR1);
    sigprocmask(SIG_SETMASK, &sigset, NULL);

    printf("before second kill()\n");
    kill(getpid(), SIGUSR1);
    printf("after second kill()\n");

    return 0;
}

这是我的程序的示例输出:

先杀之前()
catcher() 已获得控制权
在第二次杀戮之前()
在第二次杀死()之后

我能知道为什么输出的第一行是before first kill()吗?为什么catcher() has gained control 不先出现?

据我所知,sa_handler 包含两种类型的信号,信号默认和信号忽略。

我们如何知道它将产生哪个信号?如果信号忽略正在生成,为什么会触发打印 catcher() 已获得控制的函数?

此外,这个程序中的sa_mask 函数是什么?据我了解,sa_mask 会屏蔽指定的信号。

【问题讨论】:

  • 注意:不要在信号处理程序中使用 printf() 和朋友。它不是信号安全的。

标签: c linux signals


【解决方案1】:

我能知道为什么输出的第一行在 first kill() 之前吗? 为什么 catcher() 已获得控制权不先出现?

您安装了一个捕获SIGUSR1 的信号处理程序。在SIGUSR1 被传递给进程之前,正常的程序执行流程一直在发生。所以,这里:

printf("before first kill()\n");
kill(getpid(), SIGUSR1);

您仅在打印before first kill() 后生成信号。您为什么不希望它出现在catcher() has gained control 之前?换句话说,当您调用printf("before first kill()\n"); 时,还没有发出任何信号,因此您只能期望程序执行保持正常。

这一行:

kill(getpid(), SIGUSR1);

生成SIGUSR1。操作系统在方便的时候将信号传递给进程。因为您为SIGUSR1 安装了一个处理程序,所以会调用您的信号处理程序(catcher())。您在打印第一行后发出信号,因此可以预期下一行输出将来自信号处理程序。

请注意,printf(3) 不是异步信号安全的,因此从技术上讲,您不能从信号处理程序内部调用它,但对于这些玩具示例来说通常是可以的。

据我所知,sa_handler 由两种类型的信号组成,信号 默认和信号忽略。

不止于此。 struct sigactionsa_handler 字段可以有值SIG_DFL,对应于默认的信号动作(默认动作在man signal 中列出)和SIG_IGN,表示信号被忽略(什么都不发生)当它被提升时)。但是sa_handler 也可以是指向您希望在每次传递信号时调用的函数的指针。这就是您显示的代码正在执行的操作 - 它在说:嘿,当SIGUSR1 交付时,请致电catcher()

我们如何知道它将产生哪个信号?为什么会触发 如果信号,打印 catcher() 的函数已获得控制权 忽略正在生成?

当您调用 sigaction(2) 来设置处理程序时,您指示了一个信号 (SIGUSR1)。所以,catcher() 会在SIGUSR1 被传递时被调用。

此外,这个程序中的 sa_mask 函数是什么?在我的 理解,sa_mask会阻塞指定的信号。

它是一个信号掩码,在进入信号处理程序时自动安装,并在信号处理程序返回时卸载。默认情况下,即使您传递一个空掩码,被捕获的信号在进入处理程序时总是被阻止(除非在struct sigactionsa_flags 字段中设置了SA_NODEFER 标志)。但是,您可能希望在处理程序执行时阻止其他信号 - 您这样做的方式是在 sa_mask 中指示这些信号。

【讨论】:

  • @doe,它用于将问题的答案用答案打勾标记,以便响应者通过他的工作获得一些声誉。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-29
  • 2021-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-28
  • 1970-01-01
相关资源
最近更新 更多