学科分类
目录
Linux编程

信号及信号来源

信号(signal),全称软中断信号,其本质是软件层次上对中断机制的一种模拟,用于提醒进程,某件事情已经发生。Unix早期版本中就提供了信号模型,但当时的信号模型并不可靠,信号容易丢失,之后加州伯克利大学和美国的AT&T公司对信号模型做了改进,添加了可靠信号机制,POSIX标准又对可靠信号的功能和应用接口进行了标准化,逐渐发展出了如今Linux系统中使用的信号。但不同Linux版本中的信号仍有所不同,读者可以使用kill –l命令查看系统中的信号,CentOS 6.8版本的Linux系统中的信号如图1所示。

图1 Linux系统中的信号

信号的编号从1开始,其中1~31号信号为常规信号,也就是早期信号模型中的不可靠信号;34~64号信号为实时信号,用于计算机底层开发中的信号,是经POSIX标准统一过接口和功能的可靠信号。本章重点讲解的是常规信号中的部分常用信号。

信号被应用于进程间通信,但信号实际并不由进程发送,在遇到某种情况时,内核会发送某个信号到某个进程。通常产生信号的情况有以下五种:

(1)用户在终端输入某些组合按键时,终端驱动程序会通知内核产生一个信号,之后内核将该信号发送到相应进程。这些信号的功能通常为停止或终止正在占用终端的进程,如使用Ctrl+C时会发送2号信号SIGINT、使用Ctrl+\会发送3号信号SIGQUIT中断前台进程;使用Ctrl+Z时会发送20号信号SIGTSTP到正在占用终端的进程将其挂起。

(2)当硬件检测到异常时,如段错误、除0(浮点数除外)、总线错误等异常等,内核会产生信号并发送信号到正在运行的程序。

(3)满足某种软件条件时内核也会产生信号,比如alarm计时器计时结束时会发送26号信号SIGALRM到正在运行的进程。

(4)用户进程可以在程序中通过调用系统调用kill、raise、abort等,发送指定信号给指定进程或进程组。

(5)用户在shell命令行,可以使用kill命令向指定进程发送信号。在第六章中使用kill命令杀死进程,其实质就是发送9号信号SIGKILL到指定进程。

信号的产生是一个异步事件,从信号产生到信号递达进程需要一定时间,而在这个过程中,可能会因为一些原因,导致信号无法成功递达进程。Linux系统中的信号可能会处于几个状态,分别为:发送状态、阻塞状态、未决状态、递达状态和处理状态。

● 发送状态:当某种情况驱使内核发送信号时,信号会有一个短暂的发送状态;

● 阻塞状态:由于某种原因,发送的信号无法被传递,将处于阻塞状态;

● 未决状态:发送的信号被阻塞,无法到达进程,内核就会将该信号的状态设置为未决;

● 递达状态:若信号发送后没有阻塞,信号就会被成功传递并到达进程,此时为递达状态;

● 处理状态:信号被递达后会被立刻处理,此时信号处于处理状态。

信号递达进程后才可能被处理,信号的处理方式有三种:忽略、捕捉和执行默认操作。

(1)忽略:大多数信号都可以被忽略,但9号信号SIGKILL和19号信号SIGSTOP是超级用户杀死进程的可靠方法,不能被忽略。

(2)捕获:对信号做捕获处理时,进程通常需要先为该信号设置信号响应函数,这是一个回调函数,当指定信号产生时,内核会为该进程调用并执行对应的信号响应函数。9号信号SIGKILL和19号信号SIGSTOP同样不能被捕获。

(3)执行默认动作:系统为每个信号设置了一些默认动作,当信号递达,进程又未设置信号的响应函数时,系统会对进程执行信号的默认动作。

信号的默认动作有五个,分别为Term、Ign、Core、Stop和Cont,每个动作代表的含义如下:

● Term:终止进程;

● Ign:忽略信号;

● Core:终止进程,并生成Core文件;

● Stop:暂停进程;

● Cont:继续运行进程。

信号会在不同的事件发生时被发送给对应进程,每个进程对应的事件,以及进程接收到信号后的默认动作如表1所示。

表1 常规信号属性表

编号 名称 事件 默认动作
1) SIGHUP 当用户退出shell时,由该shell启动的所有进程将收到这个信号。 Term
2) SIGINT 当用户按下<Ctrl+C>组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。 Term
3) SIGQUIT 当用户按下<Ctrl+&gt;组合键时产生该信号,用户终端向正在运行中的由该终端启动的程序发出此信号。 Term
4) SIGILL CPU检测到某进程执行了非法指令时。 Core
5) SIGTRAP 该信号由断点指令或其它trap指令产生。 Core
6) SIGABRT 调用abort函数时产生该信号。 Core
7) SIGBUS 非法访问内存地址。 Core
8) SIGFPE 在发生致命的运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为0等所有的算法错误。 Core
9) SIGKILL 无条件终止进程。本信号不能被忽略、处理和阻塞。 Term
10) SIGUSE1 用户定义的信号,程序员可以在程序中定义并使用该信号。 Term
11) SIGSEGV 指示进程进行了无效内存访问。 Core
12) SIGUSR2 另外一个用户自定义信号,程序员可以在程序中定义并使用该信号。 Term
13) SIGPIPE Broken pipe向一个没有读端的管道写数据。 Term
14) SIGALRM 定时器超时,超时的时间由系统调用alarm设置。 Term
15) SIGTERM 程序结束信号,与SIGKILL不同的是,该信号可以被阻塞和终止,通常用来表示程序正常退出。执行shell命令Kill时,缺省产生这个信号。 Term
16) SIGSTKFLT Linux早期版本出现的信号,现仍保留向后兼容。 Term
17) SIGCHLD 子进程结束时,父进程会收到这个信号。 Ign
18) SIGCONT 如果进程已停止,则使其继续运行。 Cont/Ign
19) SIGSTOP 停止进程的执行。该信号不能被忽略,处理和阻塞。 Stop
20) SIGTSTP 按下<ctrl+z>组合键时发出这个信号,停止终端交互进程的运行。 Stop
21) SIGTTIN 后台进程读终端控制台。 Stop
22) SIGTTOU 该信号类似于SIGTTIN,在后台进程要向终端输出数据时发生。 Stop
23) SIGURG 套接字上有紧急数据时,向当前正在运行的进程发出些信号,报告有紧急数据到达。如网络带外数据到达时。 Ign
24) SIGXCPU 进程执行时间超过了分配给该进程的CPU时间,系统产生该信号并发送给该进程。 Term
25) SIGXFSZ 超过文件的最大长度设置。 Term
26) SIGVTALRM 虚拟时钟超时时产生该信号。类似于SIGALRM,但是该信号只计算该进程占用CPU的使用时间。 Term
27) SGIPROF 类似于SIGVTALRM,它不公包括该进程占用CPU时间还包括执行系统调用时间。 Term
28) SIGWINCH 窗口变化大小时发出。 Ign
29) SIGIO 此信号向进程指示发出了一个异步IO事件。 Ign
30) SIGPWR 关机。 Term
31) SIGSYS 无效的系统调用。 Core
点击此处
隐藏目录