Linux信号机制与信号处理

信号(signal)是Linux进程间通讯的一种机制,全称为软中断信号,也被称为软中断。信号本质上是在软件层次上对硬件中断机制的一种模拟。

与其余进程间通讯方式(例如管道、共享内存等)相比,信号所能传递的信息比较粗糙,只是一个整数。但正是因为传递的信息量少,信号也便于管理和使用,能够用于系统管理相关的任务,例如通知进程终结、停止或者恢复等。

每种信号用一个整型常量宏表示,以SIG开头,好比SIGCHLD、SIGINT等,它们在系统头文件<signal.h>中定义。

信号由内核(kernel)管理,产生方式多种多样:算法

  • 能够由内核自身产生,好比出现硬件错误、内存读取错误,分母为0的除法等,内核须要通知相应进程。编程

  • 也能够由其余进程产生并发送给内核,再由内核传递给目标进程。并发


信号传递的过程:ide

  • 内核中针对每个进程都有一个表来保存信号。进程

  • 当内核须要将信号传递给某个进程时,就在该进程对应的表中写入信号,这样就生成了信号。内存

  • 当该进程由用户态陷入内核态,再次切换到用户态以前,会查看表中的信号。若是有信号,进程就会首先执行信号对应的操做,此时叫作执行信号。it

  • 从生成信号到将信号传递给对应进程这段时间,信号处于等待状态。table

  • 咱们能够编写代码,让进程阻塞(block)某些信号,也就是让这些信号始终处于等待的状态,直到进程取消阻塞(unblock)或者忽略信号。class

信号种类

下表列出了一些常见信号:
软件

信号名称 数字表示 说明
SIGHUP 1 终端挂起或控制进程终止。当用户退出Shell时,由该进程启动的全部进程都会收到这个信号,默认动做为终止进程。
SIGINT 2 键盘中断。当用户按下<Ctrl+C>组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动做为终止进程。 
SIGQUIT 3 键盘退出键被按下。当用户按下<Ctrl+D>或<Ctrl+\>组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动做为退出程序。
SIGFPE 8 发生致命的运算错误时发出。不只包括浮点运算错误,还包括溢出及除数为0等全部的算法错误。默认动做为终止进程并产生core文件。
SIGKILL 9 无条件终止进程。进程接收到该信号会当即终止,不进行清理和暂存工做。该信号不能被忽略、处理和阻塞,它向系统管理员提供了能够杀死任何进程的方法。
SIGALRM 14 定时器超时,默认动做为终止进程。
SIGTERM 15 程序结束信号,能够由 kill 命令产生。与SIGKILL不一样的是,SIGTERM 信号能够被阻塞和终止,以便程序在退出前能够保存工做或清理临时文件等。


经过 kill -l 命令能够查看系统支持的全部信号:

$ 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

上面仅是一个演示,不一样的Linux发行版支持的信号可能不一样。

每种信号都会有一个默认动做。默认动做就是脚本或程序接收到该信号所作出的默认操做。常见的默认动做有终止进程、退出程序、忽略信号、重启暂停的进程等,上表中也对部分默认动做进行了说明。

发送信号

有多种方式能够向程序或脚本发送信号,例如按下<Ctrl+C>组合键会发送SIGINT信号,终止当前进程。

还能够经过 kill 命令发送信号,语法为:

$ kill -signal pid

signal为要发送的信号,能够是信号名称或数字;pid为接收信号的进程ID。例如:

$ kill -1 1001

将SIGHUP信号发送给进程ID为1001的程序,程序会终止执行。

又如,强制杀死ID为1001的进程:

$ kill -9 1001

捕获信号

一般状况下,直接终止进程并非咱们所但愿的。例如,按下<Ctrl+C>,进程被当即终止,不会清理建立的临时文件,带来系统垃圾,也不会保存正在进行的工做,致使须要重作。

能够经过编程来捕获这些信号,当终止信号出现时,能够先进行清场和保存处理,再退出程序。

用户程序能够经过C/C++等代码捕获信号,这将在Linux C编程中进行讲解,这里仅介绍若是经过Linux命令捕获信号。

经过 trap 命令就能够捕获信号,语法为:

$ trap commands signals

commands为Linux系统命令或用户自定义命令;signals为要捕获的信号,能够为信号名称或数字。

捕获到信号后,能够有三种处理:

  • 执行一段脚原本作一些处理工做,例如清理临时文件;

  • 接受(恢复)信号的默认操做;

  • 忽略当前信号。

1) 清理临时文件

脚本捕获到终止信号后一个常见的动做就是清理临时文件。例如:

$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2

当用户按下<Ctrl+C>后,脚本先清理临时文件 work1$$ 和 dataout$$ 再退出。

注意:exit 命令是必须的,不然脚本捕获到信号后会继续执行而不是退出。

修改上面的脚本,使接收到 SIGHUP 时进行一样的操做:

$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2

几点注意:

  • 若是执行多个命令,须要将命令用引号包围;

  • 只有脚本执行到 trap 命令时才会捕获信号;

  • 再次接收到信号时还会执行一样的操做。


上面的脚本,执行到 trap 命令时就会替换 WORKDIR 和 $$ 的值。若是但愿接收到 SIGHUP 或 SIGINT 信号时再替换其值,那么能够将命令放在单引号内,例如:

$ trap 'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2

2) 忽略信号

若是 trap 命令的 commands 为空,将会忽略接收到的信号,即不作任何处理,也不执行默认动做。例如:

$ trap '' 2

也能够同时忽略多个信号:

$ trap '' 1 2 3 15

注意:必须被引号包围,不能写成下面的形式:

$ trap  2

3) 恢复默认动做

若是但愿改变信号的默认动做后再次恢复默认动做,那么省略 trap 命令的 commands 便可,例如:

$ trap 1 2

将恢复SIGHUP 和 SIGINT 信号的默认动做。

相关文章
相关标签/搜索