Linux信号3

来源:互联网 发布:淘宝男模特排名与图片 编辑:程序博客网 时间:2024/05/23 01:23

在信号的前两个博客中分别写到了信号的产生于信号的阻塞相关内容,接下来我们今天来看看信号的捕捉!

问:何为信号的捕捉?

一、定义

    如果信号的处理动作是用户自定义的信号处理函数,当信号递达的时候就去执行这个用户定义的处理动作,就叫做 信号的捕捉。

二、sigaction函数

    第一个跟信号捕捉有关的函数就是sigaction。

   调用成功时返回0,错误时返回-1,第一个参数就是信号的编号,第二个参数是个结构体,根据act修改信号的处理动作,第三个参数是表示信号原来的处理动作,不关心时可以设置为NULL。

   我们来看看这个结构体:

   第一个参数sa_handler设置为SIG_IGN表示忽略,SIG_DFL表示执行默认动作,用户也可以自定义信号处理函数,函数返回值是void,可以带一个int参数这样就可以一次处理多个信号了。

   第二个参数sa_mask是用户希望可以屏蔽的其他的信号,当信号处理函数返回时自动恢复原来的信号屏蔽字。

   第三个参数sa_flags在这里不做讨论,一般情况我们都设置它为0就可以了。

   第四个参数sa_sigaction是实时信号这里不做讨论。

我们来看一个例子加深理解!!

三、pause函数

   pause函数的功能是挂起调用进程,直到有信号递达的时候才可以执行。该函数很特别,它是一个出错处理函数,就是只有当它执行了捕捉信号的信号处理函数之后才返回-1。

   来,想想,还有什么是出错返回的函数??????

   没错!是exec进程替换函数家族!!

   我们来写一个mysleep小程序,也就是模拟实现一个sleep的功能。

   上面这个程序就是模拟实现了sleep(3)。但是!有bug,它不是完全正确的。为什么???!!

   来分析一下原因哈,虽然pause是紧接着alarm的,但是却无法保证它一定紧挨着执行啊,可能会出现优先级高的进程突然被调度而执行,我们的进程被切换出去了,所以这种由于时序问题而导致错误,我们把它叫做 竞态条件。那我们解除上述问题很简单了,就是把“解除信号屏蔽”和“挂起等待信号”合成一步就可以了,sigsuspend这个函数就可以办到!同样地,这个函数也是出错返回。

四、可重入函数与线程安全

可重入函数:重入也就是重复调用,当函数被不同的执行流调用,因为访问全局变量或则参数而导致出错的叫不可重入函数,反之                       就叫做可重入函数。

符合下述条件之一的函数就是不可重入的:

1. 调用了malloc或者free。

2. 调用了标准I/O库函数。

什么又是线程安全?

       如果你的代码所在的进程有多个线程在同时运行,而这些线程可能会同时运行这个代码,线程之间的切换不会导致结果或者其中的变量具有二义性,那就说明这是线程安全的。要确保函数线程安全,则要考虑的是线程之间的共享变量,在对共享变量访问时,要确保是安全的则一定要加锁。

二者之间的区别于联系:

1. 线程安全是在多个线程情况下引发的,而可重入函数可以在只有一个线程的情况下进行。

2. 线程安全不一定是可重入的,但是如果是可重入的函数就一定是线程安全的。

3. 如果一个函数中有全局变量,那这个函数既不是线程安全的也不是可重入的。

4. 如果对临界资源加上锁,则这个函数是线程安全的,但如果给可重入函数加锁则会产生死锁。

5. 线程安全函数能够使不同的线程访问同一块地址空间,而可重入函数要求不同的执行流对数据的操作互不影响使结果相同。


如果以上内容有错误,欢迎批评指正!!!( ̄▽ ̄)"

0 0
原创粉丝点击