Linux中的信号(2)

来源:互联网 发布:西门子编程线 编辑:程序博客网 时间:2024/06/08 05:34

在上篇博客中,主要介绍了信号的基本概念,这次我主要介绍一下与信号相关的函数以及对它们的应用。

sigaction函数

#include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
sigaction函数可以读取和修改与指定信号相关联的处理动作。
调用成功则返回0,出错则返回- 1。
signo是指定信号的编号。
若act指针非空,则根据act修改该信号的处理动作。
若oact指针非空,则通过oact传出该信号原来的处理动作。
act和oact指向sigaction结 构体:



pause函数
#include <unistd.h>
int pause(void);

pause函数使调用进程挂起直到有信号递达。如果信号的处理动作是终止进程,则进程终止,pause函数没有机会返回;如果信号的处理动作是忽略,则进程继续处于挂起状态,pause 不返回;如果信号的处理动作是捕捉,则调用了信号处理函数之后pause返回-1,errno设置为 EINTR, 所以pause只有出错的返回值(想想以前还学过什么函数只有出错返回值?)。错误码 EINTR表示“被信号中断”。
{exec函数、pause函数只会出错返回。。。}

竞态条件与sigsuspend函数

由于异步事件在任何时候都有可能发生(这里的异步事件指出现更高优先级的进程),如果我们写程序时考虑不周密,就可能由于时序问题 而导致错误,这叫做竞态条件 (Race Condition)。



和pause一样,sigsuspend没有成功返回值,只有执行了一个信号处理函数之后 sigsuspend才返回,返回值为-1,errno设置为EINTR。
调用sigsuspend时,进程的信号屏蔽字由sigmask参数指定,可以通过指定sigmask来临时解除对某个信号的屏蔽,然后挂起等待,当sigsuspend返回时,进程的信号屏蔽字恢复为原来的值,如果原来对该信号是屏蔽的,从sigsuspend返回后仍然是屏蔽的。

首先,我们来对31个信号进行捕捉,查看有那个信号不能被捕捉:

代码如下:


我们在另外一个终端中给这个进程发送信号,看那个信号可以是程序结束:

9号信号(SIGKILL):



19号信号(SIGSTOP):



结论:这两个信号并不能捕捉


实现自己的my_sleep函数:

代码:



这是我们自己实现的my_sleep函数,看下有没有什么问题?

系统运行的时序(Timing)并不像我们写程序时所设想的那样。 虽然alarm(timeout)紧接着的下一行就是pause(),但是无法保证pause()一定会在调用alarm(timeout)之后的timeout秒之内被调用。由于异步事件在任何时候都有可能发生,这时由于时序问题就会出现错误。

怎样改进呢?

这时我们就要使用sigsuspend函数,而不是pause函数。

看下面的代码:



运行结果:












0 0
原创粉丝点击