进程间的通信可以通过信号进行通信,基于这个方式,所以kill说白了就是kill 作为一个进程,对另外一个进程发送了一个signal的信号,程序捕获这个信号,进行操作。
信号的常规使用是为了程序的优雅退出,重载,热更新等等,为了实现这个目的,程序会在代码里进行信号的监听,常规的做法就是在主程序里写个(while listen…)Linux 本身会有很多信号,可以kill -l 看下默认支持得信号。
大家习惯使用KILL -9 杀进程,不知道有没有遇到过没有杀掉进程的情况下,很多时候不会在意,再次执行又好了,主要原因是传统Linux的信号类型导致的。先看下Linux支持的信号
会发现信号从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信号的描述是
意思是SIGKILL 和 SIGSTOP 程序是无法忽略,无法捕获,也无法阻塞的,这样做的目的是为了处理那些hang死的程序。