【linux】signal信号

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()
参数含义:
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.