线程的信号处理sigaction()函数(线程五)

1.sigaction() 函数是进程的信号处理函数

返回值:若成功则返回0,若出错则返回-1

该函数有三个参数

第一个参数:信号

第二个参数:指向struct sigaction类型的结构体指针

该结构体中含有,信号屏蔽字、信号集处理函数等。

sa_handler信号机处理函数

sa_mask字段说明了一个信号集,也是信号屏蔽字。

第三个参数:也是一个结构体,只不过是一个旧状态,一般置NULL;

总结所以要是用sigaction()之前就要先定义一个struct signalaction 类型的结构体,并对其进行填充。

注意使用结构体之前首先要对其进行清空处理!!!it.s  a good habit.

此时就完成了对信号处理函数的注册,就差别人来发送信号,sigaction函数来捕获。当捕获到外来信号时候,就交给信号处理函数去处理信号(信号处理函数又在struct sigaction act的结构体中,而该结构体中又是一个联合体,所以调用sigaction函数时候,以最后一次调用为主,发送几次信号,就调用几次信号处理函数,后面代码会具体讲到)。

2.其他一些处理信号集函数

sigemptyset()     清所有信号掩码的阻塞标志

sigfillset() 设置所有信号掩码的阻塞标志

sigaddset() 增加个别信号阻塞

sigdelset() 删除个别信号阻塞

sigismember() 确定特定的信号是否在掩码中被标志为阻塞

 

扩展:什么是掩码?(摘自百度)

信号掩码 在POSIX下,每个进程有一个信号掩码(signal mask)。简单地说,信号掩码是一个"位图",其中每一位都对应着一种信号。如果位图中的某一位为1,就表示在执行当前信号的处理程序期间相应的信号暂时被"屏蔽",使得在执行的过程中不会嵌套地响应那种信号。
为什么对某一信号进行屏蔽呢?我们来看一下对CTRL_C的处理。大家知道,当一个程序正在运行时,在键盘上按一下CTRL_C,内核就会向相应的进程发出一个SIGINT 信号,而对这个信号的默认操作就是通过do_exit()结束该进程的运行。但是,有些应用程序可能对CTRL_C有自己的处理,所以就要为SIGINT另行设置一个处理程序,使它指向应用程序中的一个函数,在那个函数中对CTRL_C这个事件作出响应。但是,在实践中却发现,两次CTRL_C事件往往过于密集,有时候刚刚进入第一个信号的处理程序,第二个SIGINT信号就到达了,而第二个信号的默认操作是杀死进程,这样,第一个信号的处理程序根本没有执行完。为了避免这种情况的出现,就在执行一个信号处理程序的过程中将该种信号自动屏蔽掉。所谓"屏蔽",与将信号忽略是不同的,它只是将信号暂时"遮盖"一下,一旦屏蔽去掉,已到达的信号又继续得到处理。

3.sigpromask单进程的信号(掩码)处理函数

对于多线程的信号(掩码)处理函数pthread_sigmask()

该函数与sigprocmask函数参数一致

第一个参数:有三种形式

SIG_BLOCK:向当前信号掩码中添加set,其中set表示要阻塞的信号

SIG_UNBLOCK:向当前信号掩码中删除set,其中set表示要取消的阻塞信号

SIG_SETMASK:在当前信号掩码中替换为set,其中set表示新信号掩码

第二个参数,set是根据第一个所选定的情况决定,可以表示要阻塞的信号,要取消的阻塞信号,以及新信号掩码

第三个参数:old状态,一般置NULL。

4程序设计

大致思路:在main()中创建两个线程,用join函数等待期结束,在子线程中首先用sigaction()对SIGQUIT信号用sig_handler()函数处理处理,然后用pthread_sigmask()对SIGQUIT信号对thread_fun1和thread-fun2函数三种情况,进行掩码处理,验证,,不同的情况sigaction()是如何对信号处理函数进行处理的。

运行结构分析

       虽然在主函数中给thread_fun1和threwad_fun2函数都发送了SIGQUIT信号。但是在thread_fun1和threwad_fun2线程函数中,用pthread_sigmask()对SIGQUIT函数进行了屏蔽,所以最后函数都没有运行信号处理函数。

如果在thread_fun2对信号SIGQUIT不进行mask处理

此时运行结果

      这个运行了两次,这两次运行结果有点奇怪,因为我对第二个thread_fun2没有进行掩码(mask)处理,所以在运行thread_fun2函数的时候,sigaction函数就得到了捕获到了SIGQUIT信号,而且这个函数第二个参数是个结构体中含有union联合体,所以第二次运行时候就调用了信号处理2 函数sig_handler2()。

     此时回过头再来看,第一次运行时候的结果就不足为奇了,因为thread_fun1后运行的,在调用sigaction()函数的时候此时sigaction()已经捕获到了SIGQUIT信号,所以就调用了信号处理 1函数sig_handler1()。

扩展如果我们把thread_fun1和threwad_fun2都不屏蔽信号,此时运行结果就是

后运行的信号处理函数被调用了两次,再次说明sigaction()以最后一次运行为标准,发送几次信号,则最后一次sig_handler()信号处理函数就被调用几次函数。

      到这里多线程信号处理函数的笔记基本记完了,对我来说,这几个信号处理函数,废了我好多脑细胞,Linux学习之路,任重而道远呀。。。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值