zoukankan      html  css  js  c++  java
  • sigsuspend

    1)头文件:#include <signal.h>

    2)一个保护临界区代码的错误实例:(sigprocmask()和pause()实现)

    #include <unistd.h>
    #include <signal.h>
    #include <stdio.h>
     
    void handler(int sig)    //信号处理函数的实现
    {
       printf("SIGINT sig");
    }
    int main()
    {
        sigset_t new,old;
        struct sigaction act;
        act.sa_handler = handler;  //信号处理函数handler
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        sigaction(SIGINT, &act, 0);  //准备捕捉SIGINT信号
        sigemptyset(&new);
        sigaddset(&new, SIGINT);
        sigprocmask(SIG_BLOCK, &new, &old);  //将SIGINT信号阻塞,同时保存当前信号集
        printf("Blocked");
        sigprocmask(SIG_SETMASK, &old, NULL);  //取消阻塞
        pause();
        return 0;
    }

    上面实例的问题是:本来期望pause()之后,来SIGINT信号,可以结束程序;可是,如果当“取消阻塞”和“pause”之间,正好来了SIGINT信号,结果程序因为pause的原因会一直挂起。。。

    解决的方式,当然是sigsuspend()函数了。

     1 3)使用sigsuspend()的程序
     2 #include <unistd.h>
     3 #include <signal.h>
     4 #include <stdio.h>
     5 void handler(int sig)   //信号处理程序
     6 {
     7    if(sig == SIGINT)
     8       printf("SIGINT sig");
     9    else if(sig == SIGQUIT)
    10       printf("SIGQUIT sig");
    11    else
    12       printf("SIGUSR1 sig");
    13 }
    14  
    15 int main()
    16 {
    17     sigset_t new,old,wait;   //三个信号集
    18     struct sigaction act;
    19     act.sa_handler = handler;
    20     sigemptyset(&act.sa_mask);
    21     act.sa_flags = 0;
    22     sigaction(SIGINT, &act, 0);    //可以捕捉以下三个信号:SIGINT/SIGQUIT/SIGUSR1
    23     sigaction(SIGQUIT, &act, 0);
    24     sigaction(SIGUSR1, &act, 0);
    25    
    26     sigemptyset(&new);
    27     sigaddset(&new, SIGINT);  //SIGINT信号加入到new信号集中
    28     sigemptyset(&wait);
    29     sigaddset(&wait, SIGUSR1);  //SIGUSR1信号加入wait
    30     sigprocmask(SIG_BLOCK, &new, &old);       //将SIGINT阻塞,保存当前信号集到old中
    31    
    32     //临界区代码执行    
    33   
    34     if(sigsuspend(&wait) != -1)  //程序在此处挂起;用wait信号集替换new信号集。即:过来SIGUSR1信  号,阻塞掉,程序继续挂起;过来其他信号,例如SIGINT,则会唤醒程序。执行sigsuspend的原子操作。注意:如果“sigaddset(&wait, SIGUSR1);”这句没有,则此处不会阻塞任何信号,即过来任何信号均会唤醒程序。
    35         printf("sigsuspend error");
    36     printf("After sigsuspend");
    37     sigprocmask(SIG_SETMASK, &old, NULL);
    38     return 0;
    39 }

    sigsuspend的原子操作是:

    (1)设置新的mask阻塞当前进程(上面是用wait替换new,即阻塞SIGUSR1信号)

    (2)收到SIGUSR1信号,阻塞,程序继续挂起;收到其他信号,恢复原先的mask(即包含SIGINT信号的)。

    (3)调用该进程设置的信号处理函数(程序中如果先来SIGUSR1信号,然后过来SIGINT信号,则信号处理函数会调用两次,打印不同的内容。第一次打印SIGINT,第二次打印SIGUSR1,因为SIGUSR1是前面阻塞的)

    (4)待信号处理函数返回,sigsuspend返回了。(sigsuspend将捕捉信号和信号处理函数集成到一起了)

  • 相关阅读:
    【Android】Camera 使用浅析
    【Android】Camera 使用浅析
    每日学习总结<二> 2015-9-1
    每日学习总结<一> 2015-8-31
    【原创】利用typeface实现不同字体的调用显示及String转换为Unicode
    Android 软件开发之如何使用Eclipse Debug调试程序详解及Eclipse常用快捷键(转)
    Flask学习之 会话控制
    Vue组件介绍及开发
    Flask学习之 会话控制
    Flask学习之 请求与响应
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/6408783.html
Copyright © 2011-2022 走看看