跟结束进程相关的那些信号

项目中在使用kube-keepalived-vip时遇到了keepalived相关的Bug, 原本计划测试最新版的keepalived看是否存在同样的问题. 在将keepalived升级到当前最新版本v2.0.7之后发现每次执行kubectl delete pod <kube-keepalived-vip pod>都会出现segfault的内核错误, 且较大概率会连带出现keepalived的僵尸进程, 但对比发现通过手动执行kill -9结束keepalived进程却没有这个问题. 翻了一下runc的代码发现kubectl delete实际上(默认情况)是通过发给进程一个SIGTERM的信号让其退出, 这就是为什么手动执行kill -9没有出现同样的问题. 这里索性整理了一下与结束进程相关的信号的区别和联系.

信号

什么是信号

信号是软件中断, 很多比较重要的应用程序都需要处理信号. 信号提供了一种处理异步事件的方法. 例如, 终端用于键入中断健, 会通过信号机制停止一个程序, 或及早终止管道中的下一个程序.

UNIX系统的早期版本就已经提供信号机制, 但是这些系统(V7)所提供的信号模型并不可靠. 信号可能丢失, 并且在执行临界区代码时, 进程很难关闭所选择的信号. 4.3BSD和SVR3对信号模型都做了修改, 增加了可靠信号机制. 但是Berkeley和AT&T所做的更改之间并不兼容. 幸运的是, POSIX.1对可靠信号例程进行了标准化.

查看信号列表

Linux系统当中可直接通过kill命令加-l参数列出所有的信号, 主要依据头文件/usr/include/linux/signal.h.

可以看到所有的信号都包含一个正整数序号(序号0有特殊用途)和一个以SIG开头的简称

[root@10-10-88-192 ~]# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX [root@10-10-88-192 ~]# 结束进程相关的信号

通过kill -l可以看到操作系统总共提供了64种信号, 这里只列举了与结束进程相关的几种信号, 分别是信号序号为1、2、3、9、15的SIGHUP、SIGINT、SIGKILL、SIGTERM

SIGHUP

如果终端接口检测到一个连接断开, 则将此信号送给与该终端相关的控制进程. (与之相关的命令为nohup)

如果终端会话首进程终止, 也产生此信号. 在这种情况下, 此信号送给前台进程组中的每一个进程.

通常用此信号通知守护进程再次读取它们的配置文件. 选用SIGHUP的理由是, 守护进程不会有控制终端, 通常绝不会接收到这种信号.

这也是kube-keepalived-vip当中reload keepalived.conf的方式

kill -1 <pid>

SIGINT

用户按下中断健(一般采用DELETE或Ctrl+C)时, 终端驱动程序产生此信号并发送至前台进程组中的每一个进程.

当一个进程组在运行时失控, 特别是当进程正在屏幕上产生大量不需要的输出时, 常用此信号终止.

kill -2 <pid>

SIGQUIT

当用户在终端上按退出键(一般采用Ctrl +  ), 中断驱动程序产生此信号, 并发送给前台进程组中的所有进程.

此信号不仅终止前台进程组(如SIGINT), 同时将产生一个core文件(关于如何查看core文件, 见另一片博文《如何查看core文件》).

设计的初衷为以较温和地方式退出程序, 让程序在退出前可以清理一些临时文件或者做别的处理, 但建议最好不好清理临时文件, 方便gdb配合core文件进行Debug.

kill -3 <pid>

SIGKILL

强制立即结束进程, 相较于其他信号, SIGKILL信号不能够被进程捕获, 也不能够被忽略, 因此总是能够结束进程(如果不行, 那一定是操作系统的Bug).

不能够阻塞该信号

使用该信号一定要想清楚后果

kill -9 <pid>

SIGTERM

kill命令默认发送的终止信号.

该信号可由应用程序捕获, 故使用SIGTERM也让程序有机会在退出之前做好清理工作, 从而优雅地终止.

kill -15 <pid> 结束语

很多时候很多莫名其妙的问题或者Bug都是因为我们对一些细节的不理解或者掌握的不够透彻, 就比如结束一个进程就有这么多种方式, 你是否每一种方式都能够说清楚呢? 基础是否夯实正是从日常工作的小事积累和体现出来.

参考

https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html

《Unix环境高级编程》

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzwxg.html