信号和信号处理
本章讲述了信号和信号处理;介绍了信号和中断的统一处理,有助于从正确的角度看 待信号;将信号视为进程中断,将进程从正常执行转移到信号处理;解释了信号的来源,包括来自硬件、异常和其他进程的信号;然后举例说明了信号在Unix/Linux中的常见用法; 详细解释了 Unix/Linux中的信号处理,包括信号类型、信号向量位、信号掩码位、进程 PROC结构体中的信号处理程序以及信号处理步骤;用示例展示了如何安装信号捕捉器来处理程序异常。
信号和中断
中断:中断是I/O设备发送到CPU的外部请求,将CPU从正常执行转移到中断处理。
信号:信号是发送给进程的请求,将进程从正常执行转移到中断处理。
中断的类型:
- 人员中断
- 进程中断
- 硬件中断
- 进程的陷阱错误
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
信号的来源
- 来自硬件中断的信号:在进程执行过程中,一些硬件中断被转换为信号发送给进程。
- 来自异常的信号: 当用户模式下的进程遇到异常时, 会陷入内核模式, 生成一个信号, 并发送给自己。 常见的陷阱信号有SIGFPE (8), 表示浮点异常(除以 0), 最常 见也是最可怕的是SIGSEGV (11), 表示段错误, 等等
- 来自其他进程的信号:进程可使用kill(pid, sig)系统调用向pid标识的目标进程发送信号
进程PROC 结构体中的信号
每个进程PROC 都有一个32位向量,用来记录发送给进程的信号。在位向量中,每一
位 (0 位除外)代表一个信号编号。此外它还有一个信号MASK位向盘,用来屏蔽相应的信号。
信号处理函数
每个进程PROC都有一个信号处理数组intsig[32]o sig[32]数组的每个条目都指定了如何处理相应的信号,其中0表示DEFault(默认),1表示IGNore(忽略),其他非零值表示用户模式下预先安装的信号捕捉(处理)函数。
信号处理步骤
- 某进程处于内核模式时,会检査信号并处理未完成的信号,如果某信号有用户安 装的捕捉函数,该进程会先清除信号,获取捕捉函数地址,对于大多数陷阱信号,则将已安 装的捕捉函数重置为DEFault,,然后,它会在用户模式下返回,以执行捕捉函数,以这种方 式篡改返回路径当捕捉函数结束时.它会返间到最初的中断点,即它最后进入内核模式的 地方 因此,该进程会先迂回执行捕捉函数,然后再恢复正常执行。
- 重置用户安装的信号捕捉函数:用户安装的陷阱相关信号捕捉函数用于处理用户代 码中的陷阱错误。
- 信号和唤醒:在Unix/Linux内核中有两种SLEEP进程;深度休眠进程和浅度休眠进程。前-种进程不可中断,而后一种进程可由信号中断。如果某进程处于不可中断的 SLEEP状态,到达的信号(必须来自硬件中断或其他进程)不会唤醒进程。如果它处于可中断的SLEEP状态,到达的信号将会唤醒它。
信号与异常
Unix信号最初设计用于以下用途。
- 作为进程异常的统一处理方法:当进程遇到异常时,它会陷入内核模式,将陷阱原因 转换为信号编号,并将信号发送给自己。如果在内核模式下发生异常,内核只打印一 条PANIC错误消息,然后就停止了。如果在用户模式下发生异常,则进程通常会终 止,并以内存转储进行调试。
- 让进程通过预先安装的信号捕捉函数处理用户模式下的程序错误。这类似于MVS [IBM MVS]中的 ESPIE 宏。
・在特殊情况下,它会让某个进程通过信号杀死另一个进程。注意,这里所说的杀死并 不是直接杀死某个进程.而只是向目标进程发出“死亡”请求 为什么我们不直接杀 死某个进程呢?我们鼓励读者思考其中的原因(提示:瑞士银行有大量无人认领的 匿名账户。)