Linux信号详解

Linux信号详解教程

信号在最早的 Unix 系统中被引入,内核可用信号通知进程系统所发生的事件。

信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。进程之间可以互相通过系统调用 kill 发送软中断信号。

信号的本质

软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。

信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。进程之间可以互相通过系统调用 kill 发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。信号机制除了基本通知功能外,还可以传递附加信息。

收到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:

  1. 类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处理。
  2. 忽略某个信号,对该信号不做任何处理,就象未发生过一样。
  3. 对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信号的缺省操作是使得进程终止。进程通过系统调用 signal 来指定进程对某个信号的处理行为。

信号的种类

分类

可以从两个不同的分类角度对信号进行分类:

可靠性方面:可靠信号与不可靠信号;

与时间的关系上:实时信号与非实时信号。

可靠信号与不可靠信号

Linux 信号机制基本上是从 Unix 系统中继承过来的。早期 Unix 系统中的信号机制比较简单和原始,信号值小于 SIGRTMIN 的信号都是不可靠信号。这就是 “不可靠信号” 的来源。它的主要问题是信号可能丢失。

随着时间的发展,实践证明了有必要对信号的原始机制加以改进和扩充。由于原来定义的信号已有许多应用,不好再做改动,最终只好又新增加了一些信号,并在一开始就把它们定义为可靠信号,这些信号支持排队,不会丢失。

信号值位于 SIGRTMIN 和 SIGRTMAX 之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。Linux 在支持新版本的信号安装函数 sigation() 以及信号发送函数 sigqueue() 的同时,仍然支持早期的 signal() 信号安装函数,支持信号发送函数 kill()。

信号的可靠与不可靠只与信号值有关,与信号的发送及安装函数无关。目前 linux 中的 signal() 是通过 sigation() 函数实现的,因此,即使通过 signal() 安装的信号,在信号处理函数的结尾也不必再调用一次信号安装函数。同时,由 signal() 安装的实时信号支持排队,同样不会丢失。

对于目前 linux 的两个信号安装函数:signal() 及 sigaction() 来说,它们都不能把 SIGRTMIN 以前的信号变成可靠信号(都不支持排队,仍有可能丢失,仍然是不可靠信号),而且对 SIGRTMIN 以后的信号都支持排队。这两个函数的最大区别在于,经过 sigaction 安装的信号都能传递信息给信号处理函数,而经过 signal 安装的信号不能向信号处理函数传递信息。对于信号发送函数来说也是一样的。

实时信号与非实时信号

早期 Unix 系统只定义了 32 种信号,前 32 种信号已经有了预定义值,每个信号有了确定的用途及含义,并且每种信号都有各自的缺省动作。如按键盘的 CTRL ^C 时,会产生 SIGINT 信号,对该信号的默认反应就是进程终止。后 32 个信号表示实时信号,等同于前面阐述的可靠信号。这保证了发送的多个实时信号都被接收。

非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号。

常见信号

信号代号 信号名称 说 明
1 SIGHUP 该信号让进程立即关闭.然后重新读取配置文件之后重启
2 SIGINT 程序中止信号,用于中止前台进程。相当于输出 Ctrl+C 快捷键
8 SIGFPE 在发生致命的算术运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为 0 等其他所有的算术运算错误
9 SIGKILL 用来立即结束程序的运行。本信号不能被阻塞、处理和忽略。般用于强制中止进程
14 SIGALRM 时钟定时信号,计算的是实际的时间或时钟时间。alarm 函数使用该信号
15 SIGTERM 正常结束进程的信号,kill 命令的默认信号。如果进程已经发生了问题,那么这 个信号是无法正常中止进程的,这时我们才会尝试 SIGKILL 信号,也就是信号 9
18 SIGCONT 该信号可以让暂停的进程恢复执行。本信号不能被阻断
19 SIGSTOP 该信号可以暂停前台进程,相当于输入 Ctrl+Z 快捷键。本信号不能被阻断

信号产生主要条件

  1. 用户在终端按下某些键时,终端驱动会发送信号给前台进程,例如 Ctrl+c 产生的 SIGINT 信号、Ctrl+\ 产生 SIGQUIT 信号、Ctrl+z 产生 SIGSTOP 信号。
  2. 硬件异常产生的信号,这些条件由硬件检测并通知内核,然后内核向当前进程发送合适的信号。比如当前进程访问了非法地址,MMU(内存管理单元)会产生异常,内核将这个异常解释为 SIGSEGV 信号发送给进程。
  3. 一个进程调用 kill 函数可以发送信号给另一个进程,也可以调用 kill 命令发送信号给某一个进程,kill 命令也是调用 kill 函数实现的,如果不明确指定信号,则发送 SIGTERM 信号,该信号的默认处理动作是终止进程,当内核检测到软件条件发生时可以通过信号通知进程。

Linux信号详解教程总结

信号在最早的 Unix 系统中被引入,内核可用信号通知进程系统所发生的事件。

信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。进程之间可以互相通过系统调用 kill 发送软中断信号。