曲径通幽论坛

标题: 信号概述(Unix && Linux) [打印本页]

作者: beyes    时间: 2009-5-31 15:34
标题: 信号概述(Unix && Linux)
信号是 UNIX 中所使用的进程通信的一种古老方法。它是在软件层次上对中断机制的一种模拟,是一种异步通信方式。信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。它可以在任何时候发给某一进程,而无需知道该进程的状态。如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它为止;如果一个信号被进程设置为阻塞,则该信号传递被延迟,直到其阻塞被取消时传递给进程。

使用 kill -l 指令可以列出本机系统所支持的所有信号列表
beyes@linux-beyes:~> 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   
由上面可以看到,信号值在 32 之前的都有不同的名称,而信号值在 32 以后的都是用  SIGRTMINSIGRTMAX 开头,这就是两类典型的信号。前者是从 UNIX 系统中继承下来的信号,为不可靠信号( 也称为非实时信号 );后者是为了解决前面 “不可靠信号” 的问题而进行了更改和扩充的信号,称为“可靠信号”( 也称为实时信号 )。为什么之前的信号不可靠呢?这里先从信号的生命周期看起。

一个完整的信号生命周期可以分为 3 个重要阶段,这 3 个阶段由 4 个重要事件来刻画的:信号产生、信号在进程中注册、信号在进程中注销、执行信号处理函数:

上图中,相邻的两个事件间隔构成信号生命周期的一个阶段。要注意这里的信号处理有多种方式,一般是由内核完成,当有也可以由用户进程来完成。

一个不可靠的处理过程是这样的:如果发现该信号已经在进程中注册,那么就忽略该信号。因此,若前一个信号还未注销又产生了相同的信号就会产生信号丢失。而当可靠信号发送给一个进程时,不管该信号是否已经在进程中注册,都会被再注册一次,因此信号就不会丢失。所有可靠信号都支持排队,而不可靠信号都不支持排队。

注意
这里的信号的产生、注册、注销等都是指信号的内部实现机制,而不是信号的函数实现的。

用户进程对信号的响应可以有 3 种方式:

作者: beyes    时间: 2009-7-2 01:40
标题: 信号的来源
信号的来源有多种方式,按照产生条件的不同可以分为 “硬件” 和 “软件” 两种方式:

1、硬件方式
2、软件方式

作者: beyes    时间: 2009-7-2 02:01
标题: 可靠信号与不可靠信号
SIGHUP ( 1 号 ) 至 SIGSYS( 31 号 ) 之间的信号都是继承自 UNIX 系统,是不可靠信号。
Linux 根据 POSIX.4 标准定义了 SIGRTMIN ( 33 号 ) 与 SIGRTMAX ( 64 号 ) 之间的信号,它们都是可靠信号,也称为实时信号。linux 底下没有 16 和 32 号信号。

在 Linux 系统中,信号的可靠性是指信号是否会丢失,或者说该信号是否支持排队。当导致产生信号的时间发生时,内核就产生一个信号。信号产生后,内核通常会在进程表中设置某种形式的标志。当内核设置了这个标志,我们就说内核向一个进程递送了一个信号。信号产生 ( gernerate ) 和 递送 ( delivery ) 之间的时间间隔,称为信号未决 (pending) 。

进程可以调用 sigpending 将信号设置为阻塞,如果为进程产生了一个阻塞的信号( 拒绝递送请求 ),而对该信号的动作是捕捉该信号( 即不忽略信号 ),则内核将为该进程的此信号保持为未决状态,直到该进程对此信号接触阻塞或将对此信号的相应更改为忽略。如果在进程接触对某个信号的阻塞之前,这种喜好发生多次,那么如果信号被递送多次 ( 即信号在未决信号队列里面排队 ),则称之为可靠信号;只被递送一次的信号称为不可靠信号。
作者: beyes    时间: 2009-7-2 02:04
标题: 信号的优先级
信号实质上是软中断,中断有优先级,信号也有优先级。
如果一个进程有多个未决信号,则对于同一个未决的实时信号,内核将按照发送的顺序来递送信号。如果存在多个未决的实时信号,则值 ( 或者说编号 )越小的越先被递送。如果既存在不可靠信号,又存在可靠信号 ( 实时信号 ),虽然 POSIX 对这一情况没有明确规定,但 linux 系统和大多数遵循 POSIX 标准的操作系统一样,将优先递送不可靠信号。
作者: beyes    时间: 2012-7-25 08:38
标题: SIGTTIN 和 SIGCONT 信号
当一个后台进程组中的进程试图读其控制终端时,终端驱动程序产生此信号。比如运行下面命令:
[beyes[url=u.php?uid=10]@beyes  [/url]   ~]$ cat > tmp.txt &
[1] 1800

[1]+  已停止               cat > tmp.txt
[beyes@beyes   ~]$ fg
cat > tmp.txt
hello linux
[beyes@beyes   ~]$ cat tmp.txt
hello linux
在输完 cat > tmp.txt & 命令当并按下回车键后, shell 在后台启动 cat 进程,但是此时 cat 试图读取标准输入(控制终端)时,终端驱动程序将检测到这是个后台作业,于是会将 SIGTTIN 信号送到该后台作业。shell 检测到其子进程的状态改变(wait() 或 waitpid()),并通知我们该作业已被停止。接着,使用 fg 命令将该停止的作业送入前台运行,此时改作业被置入前台进程组,并将继续信号 (SIGCONT) 送给该进程组。当作业位于前台时,它可以读控制终端了。

前台作业和后台作业容易理解,在一个会话中,任一时刻,只能有一个前台作业,而可以有多个后台作业。这好比一个公司,一个公司中,往往有一个前台文员负责接待,而公司内部(后台)可以有多个部门负责不同的工作(后台作业)。如果有客户来访,应当先由前台文员负责接待登记,公司内部员工不能直接会见客户(试图读取终端),如果试图去做,那么被老板监控设施监控到,然后会阻止这一行为(发送 SIGTTIN 信号)。如果得到老板的允许(fg 命令运行,发送 SIGCONT 信号),那么后台的员工也可以走到前台去接待来访客户.
作者: beyes    时间: 2012-8-2 01:33
标题: SIGQUIT 信号
当用户在终端上按退出键 (Ctrl + \\) 时,产生该信号,并送至前台进程组中的所有进程。此信号不仅会终止前台进程组,同时还会产生一个 core 文件。

可以通过下面命令做上面的实验:
#ulimit -S -c unlimited     //设置后可以在当前目录下看到生成的 core.xxx 文件
# cat /dev/urandom
....按下 Ctrl + \\ 组合键...

作者: beyes    时间: 2012-8-6 11:09
标题: SIGALRM 信号
在调用 alarm() 函数设置的计时器超时时会产生该信号,另外如果 setitimer() 设置的间隔时间超时时也能产生该信号。默认情况下,SIGALRM 信号会结束进程。

alarm() 函数可参考:http://www.groad.net/bbs/read.php?tid-7329.html

setitimer() 函数可参考:http://www.groad.net/bbs/read.php?tid-3337.html




欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2