收到信号后,首先调用哪个异常处理程序?

收到信号后,首先调用哪个异常处理程序?

假设我们有一个使用该sleep()函数的 C 程序。

程序执行并进入睡眠状态。然后我们输入Ctrl+向进程c发送信号。SIGINT

我们知道收到 a 后的默认操作SIGINT是终止进程,我们还知道每当睡眠进程收到未被忽略的信号时,睡眠函数就会提前返回。

当我们输入Ctrl+后csleep()函数是先返回还是进程先终止?

答案1

默认操作SIGINT是根据文档终止进程(此处摘自signal(7)OpenBSD)。

These signals are defined in the file <signal.h>:

Name         Default Action       Description
SIGHUP       terminate process    terminal line hangup
SIGINT       terminate process    interrupt program

从理论上讲,终止不应给进程任何执行更多代码的机会。一个简单的石蕊测试可能有助于显示正在发生的情况(但不能证明在未处理的之后没有执行进程中的代码SIGINT)。

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

void sigint(int sig)
{
    fprintf(stderr, "got INT\n");
}

void warnexit(void)
{
    fprintf(stderr, "atexit\n");
}

int main(void)
{
    atexit(warnexit);
    //signal(SIGINT, sigint);
    fprintf(stderr, "%d\n", getpid());
    sleep(640);
    fprintf(stderr, "ouch!\n");
    return 0;
}

注释掉处理程序signal(...)后,acontrol+c 退出程序;没有迹象表明atexit处理程序或 ouch线路正在运行:

$ make sleepint
egcc -O2 -pipe    -o sleepint sleepint.c 
$ ./sleepint
31761
^C
$ 

取消注释处理程序后signal(...),即可到达代码的其余部分:

$ make sleepint
egcc -O2 -pipe    -o sleepint sleepint.c 
$ ./sleepint 
64094
^Cgot INT
ouch!
atexit
$ 

但请注意,SIGINT处理实际上非常复杂:shell 和其他进程通常会有SIGINT处理程序(否则 shell 将退出,这可能会很糟糕),按下control+c可能不会向前台进程组发送信号(程序可以将终端放入原始模式,例如 ncursescbreak()调用,并且会看到一个ETX键),以及不同的 shell 做不同的事情当使用 . 击中复杂命令时control+c。另外,还sigaction(2)可以使用该SA_RESTART标志来更改各种系统调用的行为方式......

相关内容