红楼梦每回梗概100字:linux的信号机制

来源:百度文库 编辑:中财网 时间:2024/04/28 04:29:13

一、信号及信号来源 
信号本质 
信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号和处理器收到一个中断请求能够说是相同的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。 
信号是进程间通信机制中唯一的异步通信机制,能够看作是异步通知,通知接收信号的进程有哪些事情发生了。信号机制经过实时扩展后,功能更加强大,除了基本通知功能外,还能够传递附加信息。 
信号来源 
信号事件的发生有两个来源:硬件来源(比如我们按下了键盘或其他硬件故障);软件来源,最常用发送信号的系统函数是kill, raise, alarm和setitimer连同sigqueue函数,软件来源还包括一些非法运算等操作。 
二、信号的种类 
能够从两个不同的分类角度对信号进行分类:(1)可靠性方面:可靠信号和不可靠信号;(2)和时间的关系上:实时信号和非实时信号。在《Linux环境进程间通信(一):管道及有名管道》的附1中列出了系统所支持的任何信号。 ! 
1、可靠信号和不可靠信号 
"不可靠信号" 
Linux信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,因此,把那些建立在早期机制上的信号叫做"不可靠信号",信号值小于SIGRTMIN(Red hat 7.2中,SIGRTMIN=32,SIGRTMAX=63)的信号都是不可靠信号。这就是"不可靠信号"的来源。他的主要问题是: 
• 进程每次处理信号后,就将对信号的响应配置为默认动作。在某些情况下,将导致对信号的错误处理;因此,用户假如不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号。 
• 信号可能丢失,后面将对此周详阐述。 
因此,早期unix下的不可靠信号主要指的是进程可能对信号做出错误的反应连同信号可能丢失。 
Linux支持不可靠信号,但是对不可靠信号机制做了改进:在调用完信号处理函数后,不必重新调用该信号的安装函数(信号安装函数是在可靠机制上的实现)。因此,Linux下的不可靠信号问题主要指的是信号可能丢失。 
"可靠信号" 
随着时间的发展,实践证实了有必要对信号的原始机制加以改进和扩充。所以,后来出现的各种Unix版本分别在这方面进行了研究,力图实现"可靠信 号"。由于原来定义的信号已有许多应用,不好再做改变,最终只好又新增加了一些信号,并在一开始就把他们定义为可靠信号,这些信号支持排队,不会丢失。同时,信号的发送和安装也出现了新版本:信号发送函数sigqueue()及信号安装函数sigaction()。
信号值位于SIGRTMIN和SIGRTMAX之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。Linux在支持新版本的信号安装 函数sigation()连同信号发送函数sigqueue()的同时,仍然支持早期的signal()信号安装函数,支持信号发送函数kill()。 
注:不要有这样的误解:由sigqueue()发送、sigaction安装的信号就是可靠的。事实上,可靠信号是指后来添加的新信号(信号值 位于SIGRTMIN及SIGRTMAX之间);不可靠信号是信号值小于SIGRTMIN的信号。信号的可靠和不可靠只和信号值有关,和信号的发送及安装 函数无关。现在linux中的signal()是通过sigation()函数实现的,因此,即使通过signal()安装的信号,在信号处理函数的结尾 也不必再调用一次信号安装函数。同时,由signal()安装的实时信号支持排队,同样不会丢失。 
对于现在linux的两个信号安装函数:signal()及sigaction()来说,他们都不能把SIGRTMIN以前的信号变成可靠信号 (都不支持排队,仍有可能丢失,仍然是不可靠信号),而且对SIGRTMIN以后的信号都支持排队。这两个函数的最大区别在于,经过sigaction安装的信号都能传递信息给信号处理函数(对任何信号这一点都成立),而经过signal安装的信号却不能向信号处理函数传递信息。对于信号发送函数来说也是相同的。 . 
2、实时信号和非实时信号 
早期Unix系统只定义了32种信号,Ret hat7.2支持64种信号,编号0-63(SIGRTMIN=31,SIGRTMAX=63),将来可能进一步增加,这需要得到内核的支持。前32种信号已有了预定义值,每个信号有了确定的用途及含义,并且每种信号都有各自的缺省动作。如按键盘的CTRL ^C时,会产生SIGINT信号,对该信号的默认反应就是进程终止。后32个信号表示实时信号,等同于前面阐述的可靠信号。这确保了发送的多个实时信号都 被接收。实时信号是POSIX标准的一部分,可用于应用进程。 
非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号。 
三、进程对信号的响应 
进程能够通过三种方式来响应一个信号:(1)忽略信号,即对信号不做任何处理,其中,有两个信号不能忽略:SIGKILL及SIGSTOP; (2)捕获信号。定义信号处理函数,当信号发生时,执行相应的处理函数;(3)执行缺省操作,Linux对每种信号都规定了默认操作注意,进程对实时信号的缺省反应是进程终止。 
Linux究竟采用上述三种方式的哪一个来响应信号,取决于传递给相应API函数的参数。 
四、信号的发送 . 
发送信号的主要函数有:kill()、raise()、 sigqueue()、alarm()、setitimer()连同abort()。 
五、信号的安装(配置信号关联动作) 
假如进程要处理某一信号,那么就要在进程中安装该信号。安装信号主要用来确定信号值及进程针对该信号值的动作之间的映射关系,即进程将要处理哪个信号;该信号被传递给进程时,将执行何种操作。 
linux主要有两个函数实现信号的安装:signal()、sigaction()。其中signal()在可靠信号系统调用的基础上实现, 是库函数。他只有两个参数,不支持信号传递信息,主要是用于前32种非实时信号的安装;而sigaction()是较新的函数(由两个系统调用实现: sys_signal连同sys_rt_sigaction),有三个参数,支持信号传递信息,主要用来和 sigqueue() 系统调用配合使用,当然,sigaction()同样支持非实时信号的安装。sigaction()优于signal()主要体现在支持信号带有参数。
六、信号集及信号集操作函数: 
信号集被定义为一种数据类型: 
typedef struct { 
unsigned long sig[_NSIG_WORDS]; 
} sigset_t 
信号集用来描述信号的集合,linux所支持的任何信号能够全部或部分的出现在信号集中,主要和信号阻塞相关函数配合使用。
七、信号阻塞和信号未决: 
每个进程都有一个用来描述哪些信号递送到进程时将被阻塞的信号集,该信号集中的任何信号在递送到进程后都将被阻塞。下面是和信号阻塞相关的几个函数: 

#include 
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)); 
int sigpending(sigset_t *set)); 
int sigsuspend(const sigset_t *mask));