简体   繁体   English

linux中的信号处理c

[英]signal handling in linux for c

I am trying to understand how signals work in Linux from the sample program that I found online, but it has some parts which I don't really understand. 我试图从我在网上找到的示例程序中了解信号在Linux中是如何工作的,但它有一些我不太懂的部分。

This is my sample program: 这是我的示例程序:

#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;
}

Here is the sample output from my program: 以下是我的程序的示例输出:

before first kill() 在第一次杀死之前()
catcher() has gained control 捕手()获得了控制权
before second kill() 在秒杀之前()
after second kill() 第二次杀戮后()

Can I know why the first line in the output is before first kill() ? 我能否知道为什么输出中的第一行是before first kill() Why doesn't catcher() has gained control appear first? 为什么catcher() has gained control首先出现?

From what I know, sa_handler consists of two types of signal, signal default and signal ignore. 据我所知, sa_handler包含两种类型的信号,信号默认和信号忽略。

How do we know which signal it will generate? 我们如何知道它将产生哪个信号? Why would it trigger the function to print the catcher() has gained control if the signal ignore being generate? 为什么它会触发打印catcher的函数()如果信号忽略生成则获得了控制权?

Besides, what is the sa_mask function in this program? 此外,这个程序中的sa_mask函数是什么? In my understanding, sa_mask will block the specified signal. 根据我的理解, sa_mask将阻止指定的信号。

Can I know why the first line in the output is before first kill()? 我能否知道为什么输出中的第一行是在第一次kill()之前? Why doesn't catcher() has gained control appear first? 为什么catcher()没有获得控制权首先出现?

You installed a signal handler that catches SIGUSR1 . 您安装了一个捕获SIGUSR1的信号处理程序。 Until SIGUSR1 is delivered to the process, normal program execution flow keeps happening. SIGUSR1交付给流程之前,正常的程序执行流程不断发生。 So, here: 所以在这里:

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

You only generate the signal after printing before first kill() . 您只能before first kill()打印后生成信号。 Why don't you expect this to appear before catcher() has gained control ? 你为什么不期望在catcher() has gained control之前出现这种情况? In other words, when you call printf("before first kill()\\n"); 换句话说,当你调用printf("before first kill()\\n"); , no signals have been raised yet, so you can only expect program execution to remain normal. ,尚未提出任何信号,因此您只能期望程序执行保持正常。

This line: 这一行:

kill(getpid(), SIGUSR1);

Generates SIGUSR1 . 生成SIGUSR1 The operating system delivers the signal to the process at a convenient time. 操作系统在方便的时间将信号传递给过程。 Because you installed a handler for SIGUSR1 , your signal handler ( catcher() ) is invoked. 因为您为SIGUSR1安装了处理程序,所以会调用您的信号处理程序( catcher() )。 You raise the signal after printing the first line, so it is expectable that the next line of output will come from the signal handler. 在打印第一行之后提升信号,因此可以预期下一行输出将来自信号处理程序。

Note that printf(3) is not async-signal safe, so technically you can't call it from inside a signal handler, but it is usually ok for these toy examples. 请注意, printf(3)不是异步信号安全的,所以从技术上讲,你不能从信号处理程序中调用它,但通常这些玩具示例都可以。

From what I know, sa_handler consists of two types of signal, signal default and signal ignore. 据我所知,sa_handler包含两种类型的信号,信号默认和信号忽略。

There's more to it than that. 除此之外还有更多。 The sa_handler field of struct sigaction can have the values SIG_DFL , which corresponds to the default signal action (the default action is listed in man signal ), and SIG_IGN , which means the signal is ignored (nothing happens when it is raised). struct sigactionsa_handler字段可以具有值SIG_DFL ,其对应于默认信号操作(默认操作在man signal列出)和SIG_IGN ,这意味着信号被忽略(在引发时没有任何反应)。 But sa_handler can also be a pointer to a function that you want to be invoked every time the signal is delivered. sa_handler也可以是指向每次传递信号时要调用的函数的指针。 This is what the code you showed is doing - it is saying: Hey, when SIGUSR1 is delivered, please call catcher() . 这就是您展示的代码正在做的事情 - 它说: 嘿,当SIGUSR1交付时,请调用catcher()

How do we know which signal it will generate? 我们如何知道它将产生哪个信号? Why would it trigger the function to print the catcher() has gained control if the signal ignore being generate? 为什么它会触发打印catcher的函数()如果信号忽略生成则获得了控制权?

You indicated a signal ( SIGUSR1 ) when you called sigaction(2) to setup the handler. 当您调用sigaction(2)来设置处理程序时,您指示了一个信号( SIGUSR1 )。 So, catcher() will be called when SIGUSR1 is delivered. 因此,当SIGUSR1交付时,将调用catcher()

Besides, what is the sa_mask function in this program? 此外,这个程序中的sa_mask函数是什么? In my understanding, sa_mask will block the specified signal. 根据我的理解,sa_mask将阻止指定的信号。

It's a signal mask that is atomically installed when the signal handler is entered, and uninstalled when the signal handler returns. 它是一个信号掩码,在输入信号处理程序时以原子方式安装,并在信号处理程序返回时卸载。 By default, even if you pass it an empty mask, the signal being caught is always blocked upon entering the handler (unless the SA_NODEFER flag is set in the sa_flags field of struct sigaction ). 默认情况下,即使您将空掩码传递给它,捕获的信号也会在进入处理程序时被阻止(除非在struct sigactionsa_flags字段中设置了SA_NODEFER标志)。 However, you might want to block other signals while the handler is executing - the way you do that is by indicating these signals in sa_mask . 但是,您可能希望在处理程序执行时阻止其他信号 - 您这样做的方法是在sa_mask指示这些信号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM