信号的概念

信号的概念

首先,每个信号都有一个名字。名字都以SIG开头。这些名字都由常量正整数定义在<signal.h>头文件中。(实际上一些实现都有自己独立的头文件,但是这些头文件也包含<signal.h>

没有任何一个信号使用常量0。0是用于kill函数的一个特别案例。POSIX.1叫这个值为空信号(null signal)。

许多条件都能产生信号:

  • 当用户按某些终端键时,终端产生信号。如ctrl+C一般来说会产生中断信号(SIGINT)。这可以停止一个无法控制的程序。
  • 硬件异常产生信号:如除数为0、无效内存索引,这样类似的情况。这些条件一般是被硬件发现的,然后通知给内核。之后内核会产生一个适当的信号,发送给当前产生异常条件的程序。例如:一个进程执行了无效的内存索引,会产生SIGSEGV信号。
  • kill函数允许一个进程发送任何信号到另一个进程或进程组中。正常情况下有个限制:我们必须是接收信号的进程所有者,或者我们必须是超级用户。
  • kill命令允许我们发送信号到另一个进程。这个程序刚好有kill函数的接口。这个命令常用于制止一个无法停止的后台进程。
  • 当某件事发生,这件事应该通知给某进程时,软件条件也能产生信号。这不是硬件产生条件(如除数为0这样的条件),而是软件条件。例如:SIGURG(当超出带宽的数据到来的时候产生),SIGPIPE(当读取PIPE的程序已经终止,进程仍然写PIPE时产生。),SIGALRM(当进程设置的始终到期时产生)

信号是异步事件的典型例子。信号可以发生在进程运行的任意时间里。进程不能简单的测试某一变量值来判断信号是否产生了。而是进程必须告诉内核“如果某一信号发生了,那么就这么干。”

我们可以让内核做下面三件事之一。我们称之为“信号处置(disposition of the signal)”或“信号关联动作”。

  1. 忽略信号。这用于多数信号,但是两种信号不能忽略:SIGKILLSIGSTOP。原因是这两种信号不能被忽略,这是给内核或超级用户提供一种可靠的结束进程的方法。如果忽略了由硬件产生的异常,那么进程的行为是未定义的。
  2. 捕获信号。这么做是告诉内核,无论可时产生了信号,就调用我们的某一程序进程处理。在我们的函数中,我们可以做任何我们想处理的条件。如果我们写了一个命令中断,当用户使用键盘产生一个中断信号时,我们可能想返回主函数,终止用户已经执行的任何命令。如果SIGCHLD信号被捕获,它意味着子进程已经终止,所以信号捕获函数可以调用waitpid去获得子进程的PID和终止状态。做为另一个例子,如果进程已经创建了临时文件,我们可能想写一个捕获SIGTERM(终止信号是kill命令默认发送的信号)信号的函数,去清除临时文件。注意:SIGKILLSIGSTOP这两个信号不能被捕获。
  3. 使用默认动作。每个信号都有一个默认动作。注意:对于多数信号来说默认动作是结束进程。

下面表格显示了信号的默认动作:

Figure 10.1. UNIX System signals

Name

Description

ISO C

SUS

FreeBSD 5.2.1

Linux 2.4.22

Mac OS X 10.3

Solaris 9

Default action

SIGABRT

abnormal termination (abort)

terminate+core

SIGALRM

timer expired (alarm)

terminate

SIGBUS

hardware fault

terminate+core

SIGCANCEL

threads library internal use

ignore

SIGCHLD

change in status of child

ignore

SIGCONT

continue stopped process

continue/ignore

SIGEMT

hardware fault

terminate+core

SIGFPE

arithmetic exception

terminate+core

SIGFREEZE

checkpoint freeze

ignore

SIGHUP

hangup

terminate

SIGILL

illegal instruction

terminate+core

SIGINFO

status request from keyboard

ignore

SIGINT

terminal interrupt character

terminate

SIGIO

asynchronous I/O

terminate/ignore

SIGIOT

hardware fault

terminate+core

SIGKILL

termination

terminate

SIGLWP

threads library internal use

ignore

SIGPIPE

write to pipe with no readers

terminate

SIGPOLL

pollable event (poll)

XSI

terminate

SIGPROF

profiling time alarm (setitimer)

XSI

terminate

SIGPWR

power fail/restart

terminate/ignore

SIGQUIT

terminal quit character

terminate+core

SIGSEGV

invalid memory reference

terminate+core

SIGSTKFLT

coprocessor stack fault

terminate

SIGSTOP

stop

stop process

SIGSYS

invalid system call

XSI

terminate+core

SIGTERM

termination

terminate

SIGTHAW

checkpoint thaw

ignore

SIGTRAP

hardware fault

XSI

terminate+core

SIGTSTP

terminal stop character

stop process

SIGTTIN

background read from control tty

stop process

SIGTTOU

background write to control tty

stop process

SIGURG

urgent condition (sockets)

ignore

SIGUSR1

user-defined signal

terminate

SIGUSR2

user-defined signal

terminate

SIGVTALRM

virtual time alarm (setitimer)

XSI

terminate

SIGWAITING

threads library internal use

ignore

SIGWINCH

terminal window size change

ignore

SIGXCPU

CPU limit exceeded (setrlimit)

XSI

terminate+core/ignore

SIGXFSZ

file size limit exceeded (setrlimit)

XSI

terminate+core/ignore

SIGXRES

resource control exceeded

ignore

SUS列上的代表它是作为POSIX.1的一部分定义的。XSI代表它是以XSI扩展为基础的。

默认动作为“terminate+core”,它意味着进程的内存镜像已经离开该进程工作目录的core文件。(因为文件被命名为core,它显示了这个功能已经做为UNIX 系统的一部分多长时间了。)这个文件能用于UNIX系统的调式工作,去检查进程结束时的状态。

PS:core文件是发行版本的功能。虽然不是POSIX.1的功能,但是它已经是Single UNIX Specification 的XSI扩展中移植实现指定的功能。

以下几种情况core文件不会产生:

  1. 进程使用了set-user-ID并且当前用户不是程序文件的所有者。
  2. 进程使用了set-group-ID并且当前用户不是程序文件的组所有者。
  3. 用户没有写当前工作目录的权限。
  4. core file已经存在,并且用户没有权限写这个文件。
  5. 文件太大(查看RLIMIT_CORE的设置)

假设core文件不存在,它的权限通常是用户读、写。

具体每个信号的描述详见APUE第10.2节

Comments are closed.