计算机学习微信公众号(jsj_xx)
信号就是软件中断,和硬件中断有很多类似之处。本文分享我们对信号这种异步事件处理的理解,仅考虑进程,不涉及多线程(如有错误,还请指正,谢谢)。
【参考linux kernel source code 4.0,syscall rt_sigaction()、send_signal()、do_signal()】
1 不可靠信号
由于信号历史悠久,我们还得从不可靠信号讲起。
不可靠的根因在于存在竞态时间窗口,毕竟异步就难以预测发生信号的时机。早期信号的问题有:
每个信号仅期望触发一次。触发完内核立即将信号处理函数重置为默认值,这样自定义处理必须手动恢复,从而在自定义信号处理里、但是在恢复这个动作前,会有一个竞态窗口。
有时阻止不了信号。由于缺少信号掩码操作,导致在pause()前可能发生信号,由于这个竞态窗口的存在从而导致pause可能再也等不到信号。
对于pause问题,setjmp是一个治标不治本的解决方案。因为它的暴力跳转会让其它的信号处理夭折,并且还不能解决好信号掩码的在迁移时的保护和恢复。
可见,这些竞态窗口的存在,就是早期信号不可靠的根因。可靠信号的一个目的,就是要消灭掉这些竞态窗口。
2 可靠信号
我们(计算机学习微信公众号:jsj_xx)的理解是:sigprocmask/sigpending/sigsetjmp/siglongjmp/sigsuspend,这些函数存在的意义就是要解决上文中提到的竞态窗口问题的!
我们逐个分析:
对于sigprocmask和sigpending,质朴的(原始的)解决方式。
最细粒度地解决竞态窗口。
sigsuspend相当于sigprocmask和pause的合成,提供设置信号掩码后等待的一个原子操作。
一个基于sigprocmask的具体应用(扩展)。一个原子的智能化(手动设置自定义掩码和自动恢复老掩码)操作。不能提供sigprocmask和其它慢速系统调用的合成,很遗憾。
siglongsetjmp和siglongjmp,则是setjmp和longjmp的信号版本,提供跳转时的信号掩码现场的保护和恢复。
然而,跳转方式依旧是一个指标不治本的方案。
可见,对于等待一个全局变量(全局变量在一个信号处理中设置)这样一个处理,总算有了完美方案:sigsuspend。结合sigaction函数,我们是这么理解的:
sigprocmask在信号处理外部实施指定的屏蔽(掩码)操作。
sigaction函数在信号处理内部实施指定的屏蔽(同一信号不可重入)操作。
这样,内外结合,自然拥有完全的可靠性。
3 兼容方案
基于sigaction函数,其中也支持对早期不可靠信号的支持:
SA_NODEFER
让信号采用早期的不自动屏蔽的行为。
SA_RESETHAND
让信号采用早期的自动重置默认处理的行为。
SA_RESTART
此信号要让系统调用重启(当然也需要系统调用的支持,像read/write/wait等慢速系统调用都是支持重启的)。
SA_INTERRUPT
此信号不要让系统调用重启。
可见,调用sigaction时指定SA_RESETHAND(参考代码,同SA_ONESHOT)和SA_NODEFER(参考代码,同SA_NOMASK)就可以完美实现早期的信号方式了。关于重启系统调用,注意SIGALRM的处理:一定不能设置为SA_RESTART方式,或者更苛刻(安全)的,需要设置为SA_INTERRUPT方式。
4 信号可重入
早期的信号处理中重置默认处理的行为,可以看作是在变通解决重入问题(当然,现在已经通过自动掩码使得同一信号处理不可重入了)。信号处理里要保证调用异步信号安全的函数。这是显然的,毕竟信号是异步处理。需要注意的是,多线程里即使信号处理中使用异步信号安全的函数,也还是需要保存和恢复errno的。
异步信号不安全函数的原因有:
使用静态数据结构
使用glibc malloc/free函数
使用标准io函数(比如printf)
信号处理中是不能使用这些不安全的函数的,否则后果很严重。触类旁通,想想fork()之后、exec()之前,子进程在这段时间里,就只能调用异步信号安全函数,这是一个道理的。
5 针对同一信号处理时再次发生的计数
传统信号(编号从1到31)是不计次数的,只计是否发生过。实时信号(编号从32到64)是记录次数的,当然是有上限的(通过ulimit查看)。
需要注意,计数区别不能成为评判信号可不可靠的标准,想想硬件中断的处理就明白了。
6 总结
可靠信号要解决的问题,无非是(早期信号的)异步处理伴随的竞态窗口问题,可以说是通过sigprocmask和sigaction联合解决了。最后要说的是,信号本质就是软件中断,因为确实形神兼备硬件中断。。。
新浪微博(@NP等不等于P)
计算机学习微信公众号(jsj_xx)
原创技术文章,感悟计算机,透彻理解计算机!
联系客服