main.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<signal.h>
int cnt = 0;
void sighandler_new(int signo, siginfo_t *psigninfo, void *pReserved)
{
int count = ++cnt;
printf("%d enter, signo: %d\n", count, signo);
sleep(3);
printf("%d leave, signo: %d\n", count, signo);
}
int main(void)
{
struct sigaction act;
act.sa_flags = SA_SIGINFO | SA_RESTART;
act.sa_sigaction = sighandler_new;
//假如SIGQUIT在信号屏蔽集合中,而程序正在执行SIGINT的信号处理函数,
//此时来了一个SIGQUIT信号,则SIGQUIT暂时被屏蔽,
//SIGINT信号处理函数执行完毕后才去执行SIGQUIT信号处理函数。
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGQUIT);
sigaction(SIGINT, &act, NULL);
char buf[8];
int iret;
do
{
iret = read(STDIN_FILENO, buf, sizeof(buf) - 1);
if(-1 == iret)
{
perror("read error");
exit(-1);
}
buf[iret] = '\0';
puts(buf);
}while(strcmp(buf, "quit\n"));
return 0;
}
编译运行
注释掉main函数中
// sigemptyset(&act.sa_mask);
// sigaddset(&act.sa_mask, SIGQUIT);
这两行代码后,编译运行结果如下
两图都是先发一个SIGINT信号,再发一个SIGQUIT信号。第一个图阻塞了SIGQUIT信号,第二个图并没阻塞SIGQUIT信号
附
man手册中有:
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
SA_RESTART:使被信号打断的系统调用自动重新发起。
如果在发生信号时,程序正阻塞在某个系统调用,例如调用read()函数,则在处理完毕信号后,接着从阻塞的系统返回。如果不指定该参数,中断处理完毕之后,read函数读取失败,如下图。