假设我们有一个使用该sleep()
函数的 C 程序。
程序执行并进入睡眠状态。然后我们输入Ctrl+向进程c发送信号。SIGINT
我们知道收到 a 后的默认操作SIGINT
是终止进程,我们还知道每当睡眠进程收到未被忽略的信号时,睡眠函数就会提前返回。
当我们输入Ctrl+后c,sleep()
函数是先返回还是进程先终止?
答案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
标志来更改各种系统调用的行为方式......