在UNIX中,信号是实现异步编程的一个非常有用的机制。UNIX中信号的具体数量与特定系统有关,一般来讲超过32个(也就是说无法用32位机上的int实现信号集)
常见的信号有:SIGKILL(终止) SIGINT(终端中断) SIGSTOP(停止) SIGCONN(继续,对应于SIGSTOP) SIGABRT(异常终止) SIGALRM(超时) SIGQUIT(终端退出) SIGCHLD(子进程状态改变) SIGTERM(终止)
信号产生的方法有5个:①shell中的kill命令 ②进程调用kill函数 ③按终端的某些组合键(如ctrl+c) ④硬件异常产生的信号 ⑤当某种软件条件发生时产生的信号
kill命令的一般用法是 kill -n pid 。其中pid是进程号,n是信号号码,常见信号中,SIGINT是2,SIGQUIT是3,SIGKILL是9,也可以用信号名代替号码,例如kill -INT pid就是发送一个SIGINT 到pid。
默认情况下(即不加-n选项)kill会发送一个SIGTERM(有些人以为是SIGKILL)到pid。在shell中,键入 kill -l 可以查看系统中的所有信号。而在终端下,键入ctrl+c会产生SIGINT,键入ctrl+ / 会产生SIGQUIT。
UNIX有3个信号是比较特殊的,分别是SIGKILL、SIGSTOP、SIGABRT。其中 SIGKILL 和 SIGSTOP 无法捕获、阻塞以及忽略(这使得超级用户可以强制终止失去控制的程序;SIGTERM同样是终止信号,但是可以屏蔽捕获)。调用abort()函数会导致内核发送一个SIGABRT信号给调用进程,在这种情况下,SIGABRT是无法阻塞、忽略的,而且即使捕获了此信号,最终进程还是会以异常状态终止;
APUE里给出了abort()函数的大致实现,看完后就明白为什么在调用abort的情况下,SIGABRT无法阻塞、忽略。
abort的实现中把设置改成了SIG_DFL,因此无论原先设置了捕获或者忽略,SIGABRT还是会终止进程。
既然是这样,那么SIGKILL和SIGSTOP是否也是用类似的方法实现的??
下面是我自己的测试代码
测试结果是输出0,也就是说对SIGKILL的设置失败了(SIGSTOP结果一样)。可见sigaction的实现应该是对SIGKILL和SIGSTOP进行了过滤(signal是用sigaction实现的,因此不进行测试)。