sigaction
用途
① 注册signum信号处理函数,并设置 ”临时信号屏蔽集“
。(本文详细对此进行了详细分析)
② 注册signum信号处理函数,接收数据—https://blog.youkuaiyun.com/weixin_36750623/article/details/91468432
临时信号屏蔽
的本质是什么?
① 假设信号A在临时信号屏蔽集sa_mask中( 设signum != A )
② 当signum信号发生时,将进入注册的信号处理函数
③ 在信号处理函数执行过程中,假如此时有信号A产生,那么信号A将被忽略(信号A变成未决状态)
④ 当信号处理函数执行完成后,未决的信号A将被递达,信号A的处理函数才被调用
注意:尽管信号A产生了多次,当信号处理函数执行完成后,信号A的处理函数仅仅被执行一次!
说了那么多废话,临时信号屏蔽
的个人理解见下:
(1) 在信号处理函数执行过程中,屏蔽集合sa_mask中包含的信号将会被暂时屏蔽!
(2) 被暂时屏蔽的信号最终仍然会递达!
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
struct sigaction { // 第二参数 act
int sa_flags; //0 —> sa_handler SA_SIGINFO —> sa_sigaction
void (*sa_handler)(int); //信号处理函数[不接受额外数据]
void (*sa_sigaction)(int, siginfo_t *, void *); //信号处理函数[能接受额外数据];sigqueue
sigset_t sa_mask; //临时屏蔽信号集
void (*sa_restorer)(void); //废弃,一般不使用
};
sa_flags决定了使用哪个信号处理函数
[ sa_flags=0] --->sa_handler
[ sa_flags=SA_SIGINFO] --->sa_sigaction
示例代码: 临时屏蔽的信号(使用act.sa_handler)
程序测试功能
- 临时屏蔽的信号
- 不带数据的信号处理函数:act.sa_flags=0 和 act.sa_handler
程序运行分析
注释 sigaddset(&act.sa_mask,SIGQUIT)
:即不暂时阻塞Ctrl+\产生的SIGQUIT信号 ;连续按Ctrl+C多次,接着按ctrl+\,程序立即被Ctrl+\产生的SIGQUIT信号终止不注释 sigaddset(&act.sa_mask,SIGQUIT)
:即暂时阻塞Ctrl+\产生的SIGQUIT信号 ;连续按Ctrl+C多次,接着按ctrl+\,程序[不会]立即被Ctrl+\产生的SIGQUIT信号终止(此时代码执行到sleep(3); 语句),直到handler信号处理函数执行完毕后,才执行SIGQUIT信号处理函数。
总结
- 通过上面两个程序执行效果对比,临时阻塞信号的含义是:如果代码进入到其他信号的处理函数,并且还在运行;处于临时阻塞信号集中的信号处理函数将被忽略变为未决状态;必须等到其他信号的处理函数执行完成后,才去变成抵达状态而调用相应的信号处理函数。
- 因此,只是临时屏蔽的作用,和前面讲的阻塞信号集合是不同的,此处并不是真正的屏蔽。
void handler(){
printf("handler: Ctrl+C \n");
sleep(3);
printf("handler: wake up \n");
}
int main(){
struct sigaction act;
act.sa_flags=0; //表示使用act.sa_handler形式的信号处理函数
act.sa_handler=handler;
sigemptyset(&act.sa_mask); //清空sa_mask
//sigaddset(&act.sa_mask,SIGQUIT); //注释?不注释?
sigaction(SIGINT,&act,NULL);
while(1){
sleep(1);
}
}