• 信号应用于事件通知


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

    有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
    ");
        flag_happen = HAPPENED;
    }
    
    int main(int argc, char* argv[])
    {
    
        signal(SIGINT, hand_sig);
    
        while ( 1 )
        {
            if (HAPPENED == flag_happen)
            {
                printf("event happened
    ");
                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
    ");
        flag_happen = HAPPENED;
    }
    
    int main(int argc, char* argv[])
    {
    
        signal(SIGINT, hand_sig);
    
        while ( UNHAPPEN == flag_happen )
        {
            pause();
        }
    
        printf("after event happened
    ");
    
        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
    ");
        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解除屏蔽,并挂起,等待事件的发生。

     

  • 相关阅读:
    nvelocity的Foreach 中使用DataTable数据
    好的博客链接收集
    Uber Shaders
    DOF
    纹理过滤模式中的Bilinear、Trilinear以及Anistropic Filtering
    开通博客了
    代码中的隐式转换问题
    使用C++/CLI封装引用BOOST库的DLL造成的问题
    在Free Radius的PAP认证过程中使用MD5密码
    (转)测试CPU是大端Big endian 还是小端Little Endian的C代码
  • 原文地址:https://www.cnblogs.com/zhangxuan/p/6694004.html
Copyright © 2020-2023  润新知