1、什么是信号
说到信号首先想到的是信号交通灯,“红灯停,绿灯行,黄灯闪闪慢慢行”。这就是信号灯在交通中起的作用。在十字路口,常见的一个现象:当为红灯时,汽车停止形式,等待行人过马路。从这个现象中,可以类比系统中的进程中断:
红灯代表一种信号
汽车行驶代表进程
行人过马路代表信号触发的事件
红灯信号使汽车停止行驶,表示信号可以中断进程;
汽车停止行使后,行人可以过马路,表示信号中断进程后可以触发另一个事件;
红灯变绿灯,行人过马路结束,汽车可以继续行驶。表示信号触发的事件结束之后,进程可以继续执行。
信号中断大概如下图:
系统中的信号载体都有一个名字,以“SIG”开头,每个信号都有对应的编号。
“信号是软件中断
”[1]。
不存在编号为0的信号。
2、Linux系统上有哪些信号
执行命令man 7 signal
或者kill -l
查看
说明:
-
SIGHUP - 1: 连接断开。
-
SIGINT - 2:中断信号,例如键盘按下:CTRL + C。
-
SIGQUIT - 3:退出信号,例如键盘按下: CTRL + \。可以进去python解释器,按下ctrl+\就会退出Python解释器。
-
SIGILL - 4:非法(硬件)指令
-
SIGTRAP - 5: 指示一个实现定义的硬件故障。执行断点指令时,常用此信号将控制转移至调试程序。(断点调试用?)
-
SIGABRT - 6: 夭折信号,进程调用abort函数时产生这种信号,进程异常终止。
-
SIGBUS - 7:
内存故障
,产生此种信号。 -
SIGFPE - 8: 表示一个算术运算异常,如除以0、浮点溢出等。
-
SIGKILL - 9: 终止信号,例如:kill -9 xxpid,用于进程的立即终止,不能被忽略或阻止,进程与其线程一起终止,适用于无响应的进程。暴力~
-
SIGUSR1 - 10: 用户定义的信号,可用于应用程序。
-
SIGSEGV - 11: 硬件异常产生的信号,比如
除数为0
、无效的内存引用
等。 -
SIGUSR2 - 12: 用户定义的信号,可用于应用程序。
-
SIGPIPE - 13: 在管道的读进程已终止后,一个进程写此管道,会产生该信号。店已打烊,请勿来访~
-
SIGALRM - 14: 闹钟信号,由alarm函数设置的定时器超时后产生此信号。
-
SIGTERM - 15: 终止信号。软终止,kill命令默认发送SIGTERM信号。该信号让程序有机会在退出之前做好清理工作,
优雅
地终止。和kill -9相比,SIGTERM不会杀死子进程。 -
SIGSTKFLT - 16: 仅由Linux定义,它出现在Linux的早期版本,企图用于数据协处理器的栈故障。该信号并非由内核产生,但仍保留以向后兼容。
-
SIGCHLD - 17: 子进程状态改变。当一个进程终止或停止时,SIGCHLD信号被送给其父进程。需要父进程去捕捉,因为SIGCHLD信号默认是忽略的。
-
SIGCOUT - 18: 使暂停进程继续。系统会根据进程状态判定默认动作,如果接收到该信号的进程是停止状态,默认动作是继续;否则默认动作是忽略此信号。
-
SIGSTOP - 19: 停止
-
SIGTSTP - 20: 停止终端输入。例如:键盘按下CTRL + Z。
-
SIGTTIN - 21: 当一个后台进程组进程试图读其控制终端时,终端驱动程序产生此信号。
-
SIGTTOU - 22: 当一个后台进程组进程试图写其控制终端时,终端驱动程序产生此信号。
-
SIGURG - 23: 在网络连接上传来带外的数据。通知进程已经发生了一个紧急情况。
-
SIGXCPU - 24: 超过
软CPU时间
(疑惑:软CPU时间指的是发生中断CPU做指定请求处理消耗的时间?)限制,则产生此信号。 -
SIGXFSZ - 25: 如果进程超过了其
软文件长度限制
,则产生此信号。 -
SIGVTALRM - 26: 当一个由setitimer(2)函数设置的
虚拟间隔时间
已经超时时,产生此信号。 -
SIGPROF - 27: 当setitimer(2)函数设置的
梗概统计间隔定时器
已经超时时产生此信号。 -
SIGWINCH - 28: 内核维持与每个终端或伪终端相关联
窗口的大小
。如果ioctl更改了窗口大小,内核会将SIGWINCH信号发送给前台进程组。 -
SIGIO - 29: 此信号指示一个异步I/O事件。
-
SIGPWR - 30: 主要用于不间断电源(UPS)的系统。如果电源失效,则UPS启动,系统如果能依靠蓄电池继续运行,无需做任何处理;如果蓄电池也不能使系统继续运行,此时就会发送SIGPWR信号给init进程,然后由init进程处理停机操作。
-
SIGSYS - 31: 当进程执行了一条机器指令,但是参数却是无效的,会产生该信号。
-
SIGRTMIN - 32: 编号32之后的信号都是自定义信号,还未接触,以后用到了在这补充~
3、信号的处理
3.1 忽略信号
大多数信号都可以执行使用忽略来处理,但是SIGKILL和SIGSTOP不能被忽略。
3.2 捕捉信号
通知内核在信号发生时,调用一个用户函数。但是SIGKILL和SIGSTOP信号不能捕捉。
3.3 执行系统默认动作
大多数信号的系统默认动作是终止该进程。
函数signal()
#include <signal.h> void (*signal(int signo, void (*func)(int)))(int);
参数含义:
-
signo: 信号名
-
func: 可以是SIG_IGN、SIG_DEL、函数地址
-
SIG_IGN: ignor,忽略此信号。
-
SIG_DEL: default,接到此信号之后的动作是系统默认动作。
-
函数地址: 信号发生时,调用指定的函数,这种处理方式叫做捕捉该信号,调用的函数叫做信号处理函数或信号捕捉函数。
4、注意
在类UNIX系统中,kill命令或kill函数被看作杀死
是不恰当的。kill只是将一个信号发送给一个进程或进程组。该信号是否终止进程取决于该信号的类型,以及进程是否安排了捕捉该信号。
比如:kill -USR1 xxxpid
是向xxxpid进程发送SIGUSR1信号。
5、参考资料
[1] W.Richard Stevens/Stephen A.rago.UNIX环境高级编程第3版[M].北京:人民邮电出版社,2014:249.