概念
每个信号都有一个数字编码。中断信号通常是编码2。
信号处理函数有点像捕鼠器。一个信号意味着什么具有破坏性的事情发射,并被捕获。
信号(signal)是一种进程间通信机制,它给应用程序提供一种异步的软件中断,使应用程序有机会接受其他程序活终端发送的命令(即信号)。应用程序收到信号后,有三种处理方式:忽略,默认,或捕捉。进程收到一个信号后,会检查对该信号的处理机制。如果是SIG_IGN,就忽略该信号;如果是SIG_DFT,则会采用系统默认的处理动作,通常是终止进程或忽略该信号;如果给该信号指定了一个处理函数(捕捉),则会中断当前进程正在执行的任务,转而去执行该信号的处理函数,返回后再继续执行被中断的任务。
为信号安装处理函数 signal
捕捉信号
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void f(int signum)
{
printf("OUCH!\n");
}
int main()
{
// 为终断信号SIGINT安装处理函数f
signal(SIGINT, f);
for(int i=0; i<5; ++i)
{
printf("hello\n");
sleep(1);
}
return 0;
}
程序有2个独立的控制流,每次按下Ctr+C,内核都会调用函数f来处理SIGINT信号。
处理多个信号 sigaction
一个进程可能被各种来源的信号中断。信号可能以任何顺序到达。signa提供了一种简单但不完整的信号处理机制。POSIX接口,即sigaction提供了复杂的、明确定义的方法来控制进程如何对各种信号组合做出反应。
定制信号处理函数 struct sigaction
struct sigaction
{
// 老的信号处理方式(SIG_DFL、SIG_INT或处理函数)
void (*sa_handler)();
// 新的信号处理方式
// 不但可以得到信号编号,还可以获悉被调用的原因以及产生问题的上下文的相关信息
void (*sa_sigaction)(int, siginfo_t *, void *);
// 指定哪些信号要被阻塞。阻塞信号时防止数据毁损的重要技术。
sigset_t sa_mask;
// 部分:
// SA_SIGINFO:使用sa_sigaction的处理函数,否则使用sa_handler的处理函数
// SA_RESETHAND:当调用信号处理函数时,将信号的处理函数重置为缺省值SIG_DFL
// SA_NODEFER:在处理信号时关闭信号自动阻塞。这样就允许递归调用信号处理函数
// SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用
int sa_flags;
}
使用sigaction
在处理SIGINT时阻塞SIGQUIT
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void inthandler(int s)
{
printf("\nCalled with signal %d\n", s);
sleep(s);
printf("\ndone handling signal %d\n", s);
}
int main()
{
struct sigaction newhandler;
newhandler.sa_handler = inthandler; // 信号处理函数
newhandler.sa_flags = SA_RESETHAND | SA_RESTART;
sigset_t blocked;
sigemptyset(&blocked); // 清空所有位
sigaddset(&blocked, SIGQUIT); // 将SIGQUIT加入阻塞列表
newhandler.sa_mask = blocked; // 设置阻塞信号集
if(sigaction(SIGINT, &newhandler, NULL) == -1)
perror("sigaction");
else
{
char x[BUFSIZ];
while(1)
{
fgets(x, BUFSIZ, stdin);
printf("input: %s", x);
}
}
}
以很快速度连续按Ctrl+C和Ctr+\,退出信号将被阻塞直到中断信号处理完毕。
连续按下Ctr+C,进程被第二个信号杀死。如果像捕获所有Ctr+C,将SA_RESTHAND掩码从sa_flags中去掉。
参考
https://blog.csdn.net/dragon101788/article/details/10438855
https://baike.baidu.com/item/sigaction/4515754?fr=aladdin
Unix/Linux编程实践教程 Bruce Molay