UNIX信号机制浅析

UNIX/Linx的信号处理非常强大,它可以完成许多顺序编程不能提供的功能,比如下面这个读终端超时的程序,因为信号的到达的时间是不确定的,系统依靠中断机制来处理函数,所以不能依赖信号的到达时间编程。

超时信号的产生和处理。

 

Unix对信号的处理分以下几种情况:

 

1)如果你不指定任何信号的处理方式,系统将会按照对每个信号的默认情况进行处理

 

2)   如果用signal或者sigaction针对特定信号绑信号处理函数,指定信号到来时会按照绑定的处理函数处理。注意调用不良的设计可能会涉及到与其他函数的互相作用问题。比如两个信号处理函数一个代码需要很长的执行时间,另一个执行时间很短而且执行完后退出程序那后一个信号就会影响前一个信号的处理,一个简单的解决办法是在处理一个信号的时候屏蔽掉可能出现的其他信号。你可以用sigprocmask函数来屏蔽,或者直接使用sigaction。在使用sigaction的时候在调用信号捕捉函数之前,struct sigaction有一个sa_mask信号集要加到进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字恢复为原先值。这样,在调用信号处理程序时就能阻塞某些信号。在信号处理程序被调用时,系统建立的新信号屏蔽字会自动包括正被递送的信号。因此保证了在处理一个给定的信号时,如果这种信号再次发生,那么它会被阻塞到对前一个信号的处理结束为止。若同一种信号多次发生,通常并不将它们排队,所以如果在某种信号被阻塞时,它发生了五次,那么对这种信号解除阻塞后,其信号处理函数通常只会被调用一次。

注意这里的不排队,是指unix下面的信号不进行排队,因为unix如BSD等只有31种信号。他们是非实时信号,而linux系统中存在更多的信号,31以后的被认为是实时信号。你可以通过kill -l查看你系统的信号。

 

3) 如果你屏蔽了一些信号,当这些信号到来时会处于pending状态,他们会等待下面两种情况
a)系统直接调用sigwait等函数对特定信号进行直接捕捉

b)系统取消对他们的屏蔽时他们再到达进程
在这个期间这些信号就在进程外等待,进程编号小于等于31的信号多次到达时只保留一个,31号以后的信号会全部保留。如果取消了对信号的屏蔽,这些信号被取出的顺序posix标准没有要求,而从实验程序来看(针对2.6kernel,实验主机fedora11)会按照信号顺序从小到大取出信号。

这个程序来自IBM developerworks. 请留意我在这个程序中的注释。

 

信号屏蔽是一个很重要的概念。下面是一个例子说明了一些信号处理函数的作用,首先进程阻塞了S I G Q U I T信号,保存了当前信号屏蔽字(以便以后恢复),然后睡眠5秒钟。在此期间所产生的退出信号都被阻塞,不递送至该进程,直到该信号不再被阻塞。在5秒睡眠结束后,检查是否有信号pending,然后将S I G Q U I T设置为不再阻塞。

注意,在设置S I G Q U I T为阻塞时,我们保存了老的屏蔽字。为了解除对该信号的阻塞,用老的屏蔽字重新设置了进程信号屏蔽字( S I G _ S E T M A S K)。另一种方法是用S I G _ U N B L O C K使阻塞的信号不再阻塞。但是,应当了解如果编写一个可能由其他人使用的函数,而且需要在函数中阻塞一个信号,则不能用S I G _ U N B L O C K解除对此信号的阻塞,这是因为此函数的调用者在调用本函数之前可能也阻塞了此信号。在这种情况下必须使用S I G _ S E T M A S K将信号屏蔽字恢复为原先值。

在睡眠期间如果产生了退出信号,那么此时该信号是未决的,但是不再受阻塞,所以在s i g p r o c m a s k返回之前,它被递送到本进程。从程序的输出中可以看到这一点: S I G Q U I T处理程序(s i g _ q u i t)中的p r i n t f语句先执行,然后再执行s i g p r o c m a s k之后的p r i n t f语句。

 

 

参考资料是Unix环境高级编程和IBM developerworks上的一些文章,以上是一些个人总结,如有不妥请指正。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值