可靠机制,不会恢复默认信号处理程序:
新的信号安装函数sigaction:sigaction函数用于改变进程收到的特定信号后的行为
int sigaction(int signum,const struct sigaction *act,const struct sigaction *old); //成功返回0,失败返回-1
struct sigaction{
void (*sa_handler)(int);
sigset_t sa_mask;//屏蔽集合
int sa_flags;
//可选
void (*sa_sigaction) (int,siginfo_t*,void*) //与void (*sa_handler)(int)任选其一,这个针对可靠信号
}
1、第一个参数为信号的值,可以为除SIGKILL以及SIGSTOP外的任何一个特定有效的信号;
2、第二个参数是一个指向结构sigaction的一个实例的指针,在结构sigaction的实例中,指定了对特定
信号的处理,可以为空,进程会以缺省的方式对信号处理;这个结构体包含了对指定信号的处理,信号传导的信息,信号处理函数执行过程中应屏蔽掉哪些函数。
3、第三个参数oldact指向的对象用来保存原来对应信号的处理函数,可以指定oldact为NULL
#include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdlib.h> #include<stdio.h> #include<errno.h> #include<string.h> #include<signal.h> #define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); }while(0) //宏要求一条语句 void handler(int sig); int main(int argc,char*argv[]) { struct sigaction act; act.sa_handler=handler; sigemptyset(&act.sa_mask); act.sa_flags=0; if(sigaction(SIGINT,&act,NULL)<0) ERR_EXIT("sigaction error "); for(;;) pause(); return 0; } void handler(int sig)//sig是signum { printf("receive a sig=%d ",sig); }
linux中signal建立在可靠机制之上(信号在安装完,执行处理函数后,信号处理函数不会自动恢复到默认),用sigaction来模拟实现signal:
#include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdlib.h> #include<stdio.h> #include<errno.h> #include<string.h> #include<signal.h> #define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); }while(0) //宏要求一条语句 void handler(int sig); __sighandler_t my_signal(int sig,__sighandler_t handler); int main(int argc,char*argv[]) { struct sigaction act; act.sa_handler=handler; sigemptyset(&act.sa_mask); act.sa_flags=0; // if(sigaction(SIGINT,&act,NULL)<0) // ERR_EXIT("sigaction error "); my_signal(SIGINT,handler); for(;;) pause(); return 0; } __sighandler_t my_signal(int sig,__sighandler_t handler)//signal出错返回SIG_ERR { struct sigaction act; struct sigaction oldact; act.sa_handler=handler; sigemptyset(&act.sa_mask); act.sa_flags=0; if(sigaction(sig,&act,&oldact)<0) return SIG_ERR; return oldact.sa_handler; } void handler(int sig)//sig是signum { printf("receive a sig=%d ",sig); }
sigaction 中sa_mask:指定信号屏蔽字(调用信号处理函数所在的线程的信号屏蔽字中),其他信号如果在信号处理程序过程中到来,则它们会在信号处理函数执行时被阻塞。等到信号处理函数运行完,被屏蔽的信号才会递达。不同于sigprocmask,sigprocmask阻塞的信号,根本不会递达, 只会处于未决状态,不会执行信号处理程序。
1 #include<unistd.h> 2 #include<sys/types.h> 3 #include<sys/stat.h> 4 #include<fcntl.h> 5 #include<stdlib.h> 6 #include<stdio.h> 7 #include<errno.h> 8 #include<string.h> 9 10 #include<signal.h> 11 #define ERR_EXIT(m) 12 do 13 { 14 perror(m); 15 exit(EXIT_FAILURE); 16 }while(0) //宏要求一条语句 17 void handler(int sig); 18 int main(int argc,char*argv[]) 19 { 20 struct sigaction act; 21 act.sa_handler=handler; 22 sigemptyset(&act.sa_mask); 23 act.sa_flags=0; 24 25 sigaddset(&act.sa_mask,SIGQUIT); 26 if(sigaction(SIGINT,&act,NULL)<0)//若不指定sa_mask,若指定的话,SIGQUIT信号在SIGINT处理程序执行期间都被阻塞。 27 ERR_EXIT("sigaction error "); 28 for(;;) 29 pause(); 30 return 0; 31 } 32 33 void handler(int sig)//sig是signum。信号处理函数过程中,屏蔽sa_mask 34 { 35 printf("receive a sig=%d ",sig); 36 sleep(5);//不设置sa_mask的话,未返回时按ctrl+直接退出,不能阻塞新的信号。阻塞结束,SIGQUIT信号递达 37 }