下载
下载
第1 0 章 信 号
10.1 引言
信号是软件中断。很多比较重要的应用程序都需处理信号。信号提供了一种处理异步事件
的方法:终端用户键入中断键,则会通过信号机构停止一个程序。
U N I X 的早期版本,就已经有信号机构,但是这些系统,例如 V 7 所提供的信号模型并不可
靠。信号可能被丢失,而且在执行临界区代码时,进程很难关闭所选择的信号。 4 . 3 B S D 和
S V R 3 对信号模型都作了更改,增加了可靠信号机制。但是这两种更改之间并不兼容。幸运的
是P O S I X . 1对可靠信号例程进行了标准化,这正是本章所说明的。
本章先对信号机制进行综述,并说明每种信号的一般用法。然后分析早期实现的问题。在
分析存在的问题之后再说明解决这些问题的方法,这样有助于加深对改进机制的理解。本章也
包含了很多并非1 0 0 %正确的实例,这样做的目的是为了对其不足之处进行讨论。
10.2 信号的概念
首先,每个信号都有一个名字。这些名字都以三个字符 S I G 开头。例如,S I G A B RT是夭折
信号,当进程调用a b o r t函数时产生这种信号。S I G A L R M是闹钟信号,当由a l a r m函数设置的时
间已经超过后产生此信号。V 7有1 5种不同的信号,S V R 4和4 . 3 + B S D均有3 1种不同的信号。
在头文件< s i g n a l . h >中,这些信号都被定义为正整数(信号编号)。没有一个信号其编号为
0。在1 0 . 9 节中将会看到k i l l 函数,对信号编号0有特殊的应用。P O S I X . 1将此种信号编号值称为
空信号。
很多条件可以产生一个信号。
• 当用户按某些终端键时,产生信号。在终端上按D E L E T E键通常产生中断信号(S I G I N T)。
这是停止一个已失去控制程序的方法。(第11章将说明此信号可被映射为终端上的任一字符。)
• 硬件异常产生信号:除数为0、无效的存储访问等等。这些条件通常由硬件检测到,并将
其通知内核。然后内核为该条件发生时正在运行的进程产生适当的信号。例如,对执行一个无
效存储访问的进程产生一个S I G S E G V。
• 进程用k i l l ( 2 )函数可将信号发送给另一个进程或进程组。自然,有些限制:接收信号进程
和发送信号进程的所有者必须相同,或发送信号进程的所有者必须是超级用户。
• 用户可用k i l l ( 1 )命令将信号发送给其他进程。此程序是 k i l l函数的界面。常用此命令终止
一个失控的后台进程。
• 当检测到某种软件条件已经发生,并将其通知有关进程时也产生信号。这里并不是指硬
件产生条件(如被 0除),而是软件条件。例如 S I G U R G ( 在网络连接上传来非规定波特率的数
据)、S I G P I P E ( 在管道的读进程已终止后一个进程写此管道 ),以及S I G A L R M (进程所设置的闹
钟时间已经超时)。
信号是异步事件的经典实例。产生信号的事件对进程而言是随机出现的。进程不能只是测
试一个变量(例如e r r n o )来判别是否发生了一个信号,而是必须告诉内核“在此信号发生时,请
执行下列操作”。
可以要求系统在某个信号出现时按照下列三种方式中的一种进行操作。
(1) 忽略此信号。大多数信号都可使用这种方式进行处理,但有两种信号却决不能被忽略。
它们是:S I G K I L L和S I G S TO P。这两种信号不能被忽略的原因是:它们向超级用户提供一种使
进程终止或停止的可靠方法。另外,如果忽略某些由硬件异常产生的信号(例如非法存储访问
或除以0),则进程的行为是未定义的。
(2) 捕捉信号。为了做到这一点要通知内核在某种信号发生时,调用一个用户函数。在用
户函数中,可执行用户希望对这种事件进行的处理。例如,若编写一个命令解释器,当用户用
键盘产生中断信号时,很可能希望返回到程序的主循环,终止系统正在为该用户执行的命令。
如果捕捉到S I G C H L D信号,则表示子进程已经终止,所以此信号的捕捉函数可以调用 w a i t p i d
以取得该子进程的进程I D 以及它的终止状态。又例如,如果进程创建了临时文件,那么可能要
为S I G T E R M 信号编写一个信号捕捉函数以清除临时文件( k i l l 命令传送的系统默认信号是终止
信号)。
(3) 执行系统默认动作。表1 0 - 1给出了对每一种信号的系统默认动作。注意,对大多数信
号的系统默认动作是终止该进程。
表1 0 - 1 列出所有信号的名字,哪些系统支持此信号以及对于信号的系统默认动作。在
P O S I X . 1 列中,表示要求此种信号。j o b 表示这是作业控制信号(仅当支持作业控制时,才要求
此种信号)。
表10-1 UNIX信号
名 字 说 明 ANSI C P O S I X . 1 S V R 4 4 . 3 + B S D 缺 省 动 作
S I G A B R T 异常终止( a b o r t ) • • • • 终止w / c o r e
S I G A L R M 超时( a l a r m ) • • • 终止
S I G B U S 硬件故障 • • 终止w / c o r e
S I G C H L D 子进程状态改变 作业 • • 忽略
S I G C O N T 使暂停进程继续 作业 • • 继续/忽略
S I G E M T 硬件故障 • • 终止w / c o r e
S I G F P E 算术异常 • • • • 终止w / c o r e
S I G H U P 连接断开 • • • 终止
S I G I L L 非法硬件指令 • • • • 终止w / c o r e
S I G I N F O 键盘状态请求 • 忽略
S I G I N T 终端中断符 • • • • 终止
S I G I O 异步I / O • • 终止/忽略
S I G I O T 硬件故障 • • 终止w / c o r e
S I G K I L L 终止 • • • 终止
S I G P I P E 写至无读进程的管道 • • • 终止
S I G P O L L 可轮询事件( p o l l ) • 终止
S I G P R O F 梗概时间超时( s e t i t i m e r ) • • 终止
S I G P W R 电源失效/再起动 • 忽略
S I G Q U I T 终端退出符 • • • 终止w / c o r e
S I G S E G V 无效存储访问 • • • • 终止w / c o r e
S I G S T O P 停止 作业 • • 暂停进程
第 1 0 章 信 号 1 9 9
下载
(续)
名 字 说 明 ANSI C P O S I X . 1 S V R 4 4 . 3 + B S D 缺 省 动 作
S I G S Y S 无效系统调用 • • 终止w / c o r e
S I G T E R M 终止 • • • • 终止
S I G T R A P 硬件故障 • • 终止w / c o r e
S I G T S T P 终端挂起符 作业 • • 停止进程
S I G T T I N 后台从控制t t y读 作业 • • 停止进程
S I G T T O U 后台向控制t t y写 作业 • • 停止进程
S I G U R G 紧急情况 • • 忽略
S I G U S R 1 用户定义信号 • • • 终止
S I G U S R 2 用户定义信号 • • • 终止
S I G V T A L R M 虚拟时间闹钟( s e t i t i m e r ) • • 终止
S I G W I N C H 终端窗口大小改变 • • 忽略
S I G X C P U 超过C P U限制( s e t r l i m i t ) • • 终止w / c o r e
S I G X F S Z 超过文件长度限制( s e t r l i m i t ) • • 终止w / c o r e
在系统默认动作列,“终止w / c o r e”表示在进程当前工作目录的 c o r e 文件中复制了该进程的
存储图像(该文件名为c o r e,由此可以看出这种功能很久之前就是 U N I X 功能的一部分)。大多
数U N I X 调试程序都使用c o r e文件以检查进程在终止时的状态。在下列条件下不产生 c o r e文件:
( a )进程是设置-用户- I D ,而且当前用户并非程序文件的所有者,或者 ( b ) 进程是设置-组- I D ,而
且当前用户并非该程序文件的组所有者,或者 ( c )用户没有写当前工作目录的许可权,或者 ( d )
文件太大(回忆7 . 11 节中的R L I M I T _ C O R E ) 。c o r e 文件的许可权(假定该文件在此之前并不存在 )
通常是用户读/写,组读和其他读。
c o r e文件的产生不是P O S I X . 1所属部分,而是很多U N I X版本的实现特征。
U N I X 第6版没有检查条件( a ) 和( b ),并且其源代码中包含如下说明:“如果你
正在找寻保护信号,那么当设置 -用户- I D 命令执行时,将可能产生大量的这种信
号”。
4 . 3 + B S D 产生名为c o r e . p ro g 的文件,其中p ro g是被执行的程序名的前 1 6个字
符。它对c o r e文件给予了某种标识,所以是一种改进特征。
表1 0 - 1 “硬件故障”对应于实现定义的硬件故障。这些名字中有很多取自 U N I X 早先在
P D P - 11 上的实现。请查看你所使用的系统的手册,以确切地确定这些信号对应于哪些错误
类型。
下面比较详细地说明这些信号。
• SIGABRT 调用a b o r t函数时(见1 0 . 1 7节)产生此信号。进程异常终止。
• SIGALRM 超过用a l a r m 函数设置的时间时产生此信号。详细情况见 1 0 . 1 0节。若由
s e t i t i m e r ( 2 )函数设置的间隔时间已经过时,那么也产生此信号。
• SIGBUS 指示一个实现定义的硬件故障。
• SIGCHLD 在一个进程终止或停止时,S I G C H L D 信号被送给其父进程。按系统默认,将
忽略此信号。如果父进程希望了解其子进程的这种状态改变,则应捕捉此信号。信号捕捉函数
中通常要调用w a i t函数以取得子进程I D和其终止状态。
2 0 0 U N I X环境高级编程
下载
系统V的早期版本有一个名为 S I G C L D (无H ) 的类似信号。这一信号具有非标准的语义,
S V R 2的手册页警告在新的程序中尽量不要使用这种信号。应用程序应当使用标准的 S I G C H L D
信号。1 0 . 7节将讨论这两个信号。
• SIGCONT 此作业控制信号送给需要继续运行的处于停止状态的进程。如果接收到此信
号的进程处于停止状态,则系统默认动作是使该进程继续运行,否则默认动作是忽略此信号。
例如,v i编辑程序在捕捉到此信号后,重新绘制终端屏幕。关于进一步的情况见 1 0 . 2 0节。
• SIGEMT 指示一个实现定义的硬件故障。
E M T这一名字来自P D P - 11的emulator trap 指令。
• SIGFPE 此信号表示一个算术运算异常,例如除以0,浮点溢出等。
• SIGHUP 如果终端界面检测到一个连接断开,则将此信号送给与该终端相关的控制进程
(对话期首进程)。见图9 - 11 ,此信号被送给s e s s i o n 结构中s _ l e a d e r 字段所指向的进程。仅当终
端的C L O C A L 标志没有设置时,在上述条件下才产生此信号。(如果所连接的终端是本地的,
才设置该终端的C L O C A L 标志。它告诉终端驱动程序忽略所有调制解调器的状态行。第 11章将
说明如何设置此标志。)注意,接到此信号的对话期首进程可能在后台,作为一个例子见图9 - 7。
这区别于通常由终端产生的信号(中断、退出和挂起),这些信号总是传递给前台进程组。
如果对话期前进程终止,则也产生此信号。在这种情况,此信号送给前台进程组中的每一
个进程。
通常用此信号通知精灵进程(见第1 3章)以再读它们的配置文件。选用 S I G H U P的理由是,
因为一个精灵进程不会有一个控制终端,而且通常决不会接收到这种信号。
• SIGILL 此信号指示进程已执行一条非法硬件指令。
4 . 3 B S D 由a b o r t函数产生此信号。S I G A B RT 现在被用于此。
• SIGINFO 这是一种4 . 3 + B S D 信号,当用户按状态键(一般采用C t r l - T)时,终端驱动程
序产生此信号并送至前台进程组中的每一个进程(见图 9 - 8)。此信号通常造成在终端上显示前
台进程组中各进程的状态信息。
• SIGINT 当用户按中断键(一般采用D E L E T E 或C t r l - C)时,终端驱动程序产生此信号并
送至前台进程组中的每一个进程(见图9 - 8 ) 。当一个进程在运行时失控,特别是它正在屏幕上产
生大量不需要的输出时,常用此信号终止它。
• SIGIO 此信号指示一个异步I / O事件。在1 2 . 6 . 2节中将对此进行讨论。
在表1 0 - 1中,对S I G I O的系统默认动作是终止或忽略。不幸的是,这依赖于系
统。在S V R 4 中,S I G I O 与S I G P O L L相同,其默认动作是终止此进程。在 4 . 3 + B S D
中(此信号起源于4 . 2 B S D ),其默认动作是忽略。
• SIGIOT 这指示一个实现定义的硬件故障。
I O T 这个名字来自于P D P - 11对于输入/输出TRAP(input/output TRAP)指令的
缩写。系统V的早期版本,由a b o r t函数产生此信号。S I G A B RT现在被用于此。
• SIGKILL 这是两个不能被捕捉或忽略信号中的一个。它向系统管理员提供了一种可以
第 1 0 章 信 号 2 0 1
下载