当前位置:嗨网首页>书籍在线阅读

05-硬件产生的信号

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

22.4 硬件产生的信号

硬件异常可以产生SIGBUS、SIGFPE、SIGILL,和SIGSEGV信号,调用kill()函数来发送此类信号是另一种途径,但较为少见。SUSv3规定,在硬件异常的情况下,如果进程从此类信号的处理器函数中返回,亦或进程忽略或阻塞了此类信号,那么进程的行为未定义。原因如下。

  • 从信号处理器中返回:假设机器语言指令产生了上述信号之一,并因此而调用了信号处理器函数。当从处理器函数正常返回后,程序会尝试从其中断处恢复执行。可当初引发信号产生的恰恰正是这条指令,所以信号会再次“光临”。故事的结局通常是,程序进入无限循环,重复调用信号处理器函数。
  • 忽略信号:忽略因硬件而产生的信号于情理不合,试想算术异常之后,程序应当如何继续执行呢?无法明确。当由于硬件异常而产生上述信号之一时,Linux会强制传递信号,即使程序已经请求忽略此类信号。
  • 阻塞信号。与上一种情况一样,阻塞因硬件而产生的信号也不合情理:不清楚程序随后应当如何继续执行。在2.4以及更早的版本中,Linux内核仅会将阻塞硬件产生信号的种种企图一一忽略,信号无论如何都会传递给进程,随后要么进程终止,要么信号处理器会捕获信号——在程序安装有信号处理器的情况下。始于Linux 2.6,如果信号遭到阻塞,那么该信号总是会立刻杀死进程,即使进程已经为此信号安装了处理器函数。(对于因硬件而产生的信号,Linux 2.6之所以会改变对其处于阻塞状态下的处理方式,是由于Linux 2.4的行为中隐藏有缺陷,并可能在多线程程序中引起死锁。)

随本书发布源码中的signals/demo_SIGFPE.c程序就展示了忽略或者阻塞SIGFPE信号的后果,或者可正常返回的处理器将其捕获的结果。

正确处理硬件产生信号的方法有二:要么接受信号的默认行为(进程终止);要么为其编写不会正常返回的处理器函数。除了正常返回之外,终结处理器执行的手段还包括调用_exit()以终止进程,或者调用siglongjmp()(21.2.1节),确保将控制传递回程序中(产生信号的指令位置之外)的某一位置。