信号和信号处理

本章讲述了信号和信号处理;介绍了信号和中断的统一处理,有助于从正确的角度看 待信号;将信号视为进程中断,将进程从正常执行转移到信号处理;解释了信号的来源,包括来自硬件、异常和其他进程的信号;然后举例说明了信号在Unix/Linux中的常见用法; 详细解释了 Unix/Linux中的信号处理,包括信号类型、信号向量位、信号掩码位、进程 PROC结构体中的信号处理程序以及信号处理步骤;用示例展示了如何安装信号捕捉器来处理程序异常。

信号和中断

中断:中断是I/O设备发送到CPU的外部请求,将CPU从正常执行转移到中断处理。
信号:信号是发送给进程的请求,将进程从正常执行转移到中断处理。
中断的类型:

  1. 人员中断
  2. 进程中断
  3. 硬件中断
  4. 进程的陷阱错误

Unix/Linux 中的信号处理

Unix/Linux 支待31种不同的信号, 每种信号在 signal.h 文件中都有定义

#define SIGHUP 
#define SIGINT 
#define SIGQUIT #define SIGILL 
#define SIGTRAP #define SIGABRT #define SIGIOT 
#define SIGBUS 
#define SIGFPE 
#define SIGKILL 
#define SIGUSRl 
#define SIGSEGV 
#define SIGUSR2 
#define SIGPIPE 
#define SIGALRM 
#define SIGTERM 
#define SIGSTKFLT 
#define SIGCHLD 
#define SIGCONT 
#define SIGSTOP 
#define SIGTSTP 
#define SIGTTIN 
#define SIGTTOU 
#define SIGURG 
#define SIGXCPU 
#define SIGXFSZ 
#define SIGVTALRM 
#define SIGPROF 
#define SIGWINCH 
#define SIGPOLL 
#define SIGPWR 
#define SIGSYS 

信号的来源

  1. 来自硬件中断的信号:在进程执行过程中,一些硬件中断被转换为信号发送给进程。
  2. 来自异常的信号: 当用户模式下的进程遇到异常时, 会陷入内核模式, 生成一个信号, 并发送给自己。 常见的陷阱信号有SIGFPE (8), 表示浮点异常(除以 0), 最常 见也是最可怕的是SIGSEGV (11), 表示段错误, 等等
  3. 来自其他进程的信号:进程可使用kill(pid, sig)系统调用向pid标识的目标进程发送信号

进程PROC 结构体中的信号

每个进程PROC 都有一个32位向量,用来记录发送给进程的信号。在位向量中,每一
位 (0 位除外)代表一个信号编号。此外它还有一个信号MASK位向盘,用来屏蔽相应的信号。

信号处理函数

每个进程PROC都有一个信号处理数组intsig[32]o sig[32]数组的每个条目都指定了如何处理相应的信号,其中0表示DEFault(默认),1表示IGNore(忽略),其他非零值表示用户模式下预先安装的信号捕捉(处理)函数。

信号处理步骤

  1. 某进程处于内核模式时,会检査信号并处理未完成的信号,如果某信号有用户安 装的捕捉函数,该进程会先清除信号,获取捕捉函数地址,对于大多数陷阱信号,则将已安 装的捕捉函数重置为DEFault,,然后,它会在用户模式下返回,以执行捕捉函数,以这种方 式篡改返回路径当捕捉函数结束时.它会返间到最初的中断点,即它最后进入内核模式的 地方 因此,该进程会先迂回执行捕捉函数,然后再恢复正常执行。
  2. 重置用户安装的信号捕捉函数:用户安装的陷阱相关信号捕捉函数用于处理用户代 码中的陷阱错误。
  3. 信号和唤醒:在Unix/Linux内核中有两种SLEEP进程;深度休眠进程和浅度休眠进程。前-种进程不可中断,而后一种进程可由信号中断。如果某进程处于不可中断的 SLEEP状态,到达的信号(必须来自硬件中断或其他进程)不会唤醒进程。如果它处于可中断的SLEEP状态,到达的信号将会唤醒它。

信号与异常

Unix信号最初设计用于以下用途。

  • 作为进程异常的统一处理方法:当进程遇到异常时,它会陷入内核模式,将陷阱原因 转换为信号编号,并将信号发送给自己。如果在内核模式下发生异常,内核只打印一 条PANIC错误消息,然后就停止了。如果在用户模式下发生异常,则进程通常会终 止,并以内存转储进行调试。
  • 让进程通过预先安装的信号捕捉函数处理用户模式下的程序错误。这类似于MVS [IBM MVS]中的 ESPIE 宏。
    ・在特殊情况下,它会让某个进程通过信号杀死另一个进程。注意,这里所说的杀死并 不是直接杀死某个进程.而只是向目标进程发出“死亡”请求 为什么我们不直接杀 死某个进程呢?我们鼓励读者思考其中的原因(提示:瑞士银行有大量无人认领的 匿名账户。)