Kill 与信号

进程间的通信可以通过信号进行通信,基于这个方式,所以kill说白了就是kill 作为一个进程,对另外一个进程发送了一个signal的信号,程序捕获这个信号,进行操作。

信号的作用

信号的常规使用是为了程序的优雅退出,重载,热更新等等,为了实现这个目的,程序会在代码里进行信号的监听,常规的做法就是在主程序里写个(while listen…)Linux 本身会有很多信号,可以kill -l 看下默认支持得信号。

信号得种类

大家习惯使用KILL -9 杀进程,不知道有没有遇到过没有杀掉进程的情况下,很多时候不会在意,再次执行又好了,主要原因是传统Linux的信号类型导致的。先看下Linux支持的信号
Linux Signal(信号)_Linux Signal

会发现信号从31 到34 跳开了,因为1~31之间的所有信号是Unix的传统信号,都称为不可靠信号,原因就在于信号不可排队,如果kernel发现同一个信号已经有挂起信号,当前信号就会被丢弃,就好象从来没有被发送过一样,无法引起信号的传递,也无法让进程执行信号处理函数。这种实现的机理,造成了这些信号的不可靠。而34之后的信号,则被称之为可靠信号,因为加入了队列机制,同一个种类的信号可以加入队列,不会被丢弃。

1-31的传统信号如下:

SIGHUP       1          /* Hangup (POSIX).  */                          终止进程     终端线路挂断
SIGINT       2          /* Interrupt (ANSI).  */                        终止进程     中断进程 Ctrl+C
SIGQUIT      3          /* Quit (POSIX).  */                            建立CORE文件终止进程,并且生成core文件 Ctrl+\
SIGILL       4          /* Illegal instruction (ANSI).  */              建立CORE文件,非法指令
SIGTRAP      5          /* Trace trap (POSIX).  */                      建立CORE文件,跟踪自陷
SIGABRT      6          /* Abort (ANSI).  */
SIGIOT       6          /* IOT trap (4.2 BSD).  */                      建立CORE文件,执行I/O自陷
SIGBUS       7          /* BUS error (4.2 BSD).  */                     建立CORE文件,总线错误
SIGFPE       8          /* Floating-point exception (ANSI).  */         建立CORE文件,浮点异常
SIGKILL      9          /* Kill, unblockable (POSIX).  */               终止进程     杀死进程
SIGUSR1      10         /* User-defined signal 1 (POSIX).  */           终止进程     用户定义信号1
SIGSEGV      11         /* Segmentation violation (ANSI).  */           建立CORE文件,段非法错误
SIGUSR2      12         /* User-defined signal 2 (POSIX).  */           终止进程     用户定义信号2
SIGPIPE      13         /* Broken pipe (POSIX).  */                     终止进程     向一个没有读进程的管道写数据
SIGALARM     14         /* Alarm clock (POSIX).  */                     终止进程     计时器到时
SIGTERM      15         /* Termination (ANSI).  */                      终止进程     软件终止信号
SIGSTKFLT    16         /* Stack fault.  */
SIGCLD       SIGCHLD    /* Same as SIGCHLD (System V).  */
SIGCHLD      17         /* Child status has changed (POSIX).  */        忽略信号     当子进程停止或退出时通知父进程
SIGCONT      18         /* Continue (POSIX).  */                        忽略信号     继续执行一个停止的进程
SIGSTOP      19         /* Stop, unblockable (POSIX).  */               停止进程     非终端来的停止信号
SIGTSTP      20         /* Keyboard stop (POSIX).  */                   停止进程     终端来的停止信号 Ctrl+Z
SIGTTIN      21         /* Background read from tty (POSIX).  */        停止进程     后台进程读终端
SIGTTOU      22         /* Background write to tty (POSIX).  */         停止进程     后台进程写终端
SIGURG       23         /* Urgent condition on socket (4.2 BSD).  */    忽略信号     I/O紧急信号
SIGXCPU      24         /* CPU limit exceeded (4.2 BSD).  */            终止进程     CPU时限超时
SIGXFSZ      25         /* File size limit exceeded (4.2 BSD).  */      终止进程     文件长度过长
SIGVTALRM    26         /* Virtual alarm clock (4.2 BSD).  */           终止进程     虚拟计时器到时
SIGPROF      27         /* Profiling alarm clock (4.2 BSD).  */         终止进程     统计分布图用计时器到时
SIGWINCH     28         /* Window size change (4.3 BSD, Sun).  */       忽略信号     窗口大小发生变化
SIGPOLL      SIGIO      /* Pollable event occurred (System V).  */
SIGIO        29         /* I/O now possible (4.2 BSD).  */              忽略信号     描述符上可以进行I/O
SIGPWR       30         /* Power failure restart (System V).  */
SIGSYS       31         /* Bad system call.  */
SIGUNUSED    31

常用的其实也就是-9 -HUP等,其他的可以备用。其中有2个信号非常有用,即USER1 USER2,作为用户自定义信号,程序可以自定义这2个信号的含义,在收到这2个信号的时候,可以自定义代码进行对着2个信号的处理,另外如果代码里没有处理-9 的信号,程序依然会被杀掉,这是因为如果没有对应处理的对应信号的代码逻辑,则会走默认的信号策略,即上表的第四列,并且,类似-9的信号,这些signal是不作用于程序本身的,是直接作用于init进程的,可以通过https://man7.org/linux/man-pages/man7/signal.7.html看到,对于-9信号的描述是

Linux Signal(信号)_Linux Signal_02

意思是SIGKILL 和 SIGSTOP 程序是无法忽略,无法捕获,也无法阻塞的,这样做的目的是为了处理那些hang死的程序。