实际应用中,进程常常需要等待某一事件的发生,一般可以通过检测某一全局变量来判断事件是否发生。
有3种方法可以实现这一要求:
1、
程序不停的循环检查全局变量,这样可以满足要求,但是非常占用CPU资源。
2、
进程使用pause挂起,等待信号的触发,事件发生时向进程发送信号,对应的信号处理函数改变全局变量的值,信号处理函数返回后进程
检测该全局变量,满足要求即可知道事件已发生。
3、原理与第二种方法一致,不过使用的是函数sigsuspend
示例1:
//采用循环检测来判断事件的发生:
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#define HAPPENED 1
#define UNHAPPEN 0
//定义全局变量以标识事件是否发生
int flag_happen;
void hand_sig(int sinno)
{
printf("recv SIGINT\n");
flag_happen = HAPPENED;
}
int main(int argc, char* argv[])
{
signal(SIGINT, hand_sig);
while ( 1 )
{
if (HAPPENED == flag_happen)
{
printf("event happened\n");
break;
}
}
return 0;
}
示例2:
//pause挂起等待事件的发生
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#define HAPPENED 1
#define UNHAPPEN 0
//定义全局变量以标识事件是否发生
int flag_happen;
void hand_sig(int sinno)
{
printf("recv SIGINT\n");
flag_happen = HAPPENED;
}
int main(int argc, char* argv[])
{
signal(SIGINT, hand_sig);
while ( UNHAPPEN == flag_happen )
{
pause();
}
printf("after event happened\n");
return 0;
}
本程序存在一个潜在的bug:当信号发生在while之后,pause之前时,程序将检测不到事件的发生。此时,执行信号处理函数,flag_happen将被修改为
HAPPENED,之后调用pause,而这时信号都已经被处理完了,自然pause将一直挂起,那么进程不会检测到此次事件的发生。
示例3:
使用sigsuspend函数挂起等待事件的发生。
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#define HAPPENED 1
#define UNHAPPEN 0
//定义全局变量以标识事件是否发生
int flag_happen;
void hand_signal(int sinno)
{
printf("recv SIGINT\n");
flag_happen = HAPPENED;
}
int main(int argc, char* argv[])
{
flag_happen = UNHAPPEN;
sigset_t newset, oldset, zeroset;
signal(SIGINT, hand_signal);
sigemptyset(&newset);
sigemptyset(&oldset);
sigemptyset(&zeroset);
sigaddset(&newset, SIGINT);
sigprocmask(SIG_BLOCK, &newset, &oldset);
//临界区
//使用sigsuspend取消所有信号的屏蔽并等待信号的触发
while(UNHAPPEN == flag_happen)
{
sigsuspend(&zeroset);
}
//恢复信号屏蔽字
sigprocmask(SIG_SETMASK, &oldset, NULL);
return 0;
}
程序首先将SIGINT屏蔽,然后使用sigsuspend解除屏蔽,并挂起,等待事件的发生。