实际应用中,进程常常需要等待某一事件的发生,一般可以通过检测某一全局变量来判断事件是否发生。

有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解除屏蔽,并挂起,等待事件的发生。

 

 

posted on 2017-04-11 16:10  邶风  阅读(254)  评论(0编辑  收藏  举报