• sigemptyset,sigfillset,sigaddset,sigdelset,sigismember,sigprocmask,sigpendmask作用


    SYNOPSIS
           #include <signal.h>
    
           int sigemptyset(sigset_t *set);
    
           int sigfillset(sigset_t *set);
    
           int sigaddset(sigset_t *set, int signum);
    
           int sigdelset(sigset_t *set, int signum);
    
           int sigismember(const sigset_t *set, int signum);

    以上都是信号集操作函数,如果是glibc,还额外提供了以下3个函数

           int sigisemptyset(sigset_t *set);
    
           int sigorset(sigset_t *dest, sigset_t *left, sigset_t *right);
    
           int sigandset(sigset_t *dest, sigset_t *left, sigset_t *right);

    描述:

      查看linux3.13 signal.h文件源码,一共有31个用户可用的信号,信号集用每一位对应于一个信号。

      sigemptyset

        初始化信号集set,将指定的信号集set清空,即set的值为0。

      sigfillset

        初始化信号集set,将指定的信号集set全部置位,即set值为0x7FFFFFFF

      sigaddset

        将信号signum对应于信号集set的那一位置位

      sigdelset

        将信号signum对应于信号集set的那一位清零

      以上4个函数成功返回0,否则返回-1

      sigismember

        查询信号signum是否在信号集中置位了。如果置位了,返回1,否则返回0

     glibc的扩展信号集操作函数:

      sigisemptyset

        信号集set是否清空了

      sigorset

        获得信号集left,right的并集,存放到dest

      sigandset

        获得信号集left,right的交集,存放到dest

    扩展函数的测试程序:

     1     sigset_t sigdest, sigleft, sigright;
     2 
     3     sigemptyset(&sigdest);
     4     sigemptyset(&sigleft);    
     5     sigemptyset(&sigright);
     6 
     7     sigaddset(&sigleft, SIGALRM);
     8     sigaddset(&sigleft, SIGINT);
     9 
    10     sigaddset(&sigright, SIGALRM);
    11     sigaddset(&sigright, SIGQUIT);
    12 
    13     
    14     printf("
    SIG union
    ");
    15     sigorset(&sigdest, &sigleft, &sigright);
    16     if ( sigismember(&sigdest, SIGALRM ) )
    17     {
    18         printf("SIGALRM
    ");
    19     }
    20     if ( sigismember(&sigdest, SIGINT ) )
    21     {
    22         printf("SIGINT
    ");
    23     }
    24     if ( sigismember(&sigdest, SIGQUIT ) )
    25     {
    26         printf("SIGQUIT
    ");
    27     }
    28 
    29     printf("
    SIG intersection
    ");
    30     sigemptyset(&sigdest);
    31     sigandset(&sigdest, &sigleft, &sigright);
    32     if ( sigismember(&sigdest, SIGALRM ) )
    33     {
    34         printf("SIGALRM
    ");
    35     }
    36     if ( sigismember(&sigdest, SIGINT ) )
    37     {
    38         printf("SIGINT
    ");
    39     }
    40     if ( sigismember(&sigdest, SIGQUIT ) )
    41     {
    42         printf("SIGQUIT
    ");
    43     }

    运行结果:

    SIG union
    SIGALRM
    SIGINT
    SIGQUIT
    
    SIG intersection
    SIGALRM

    sigprocmask函数

    SYNOPSIS
           #include <signal.h>
    
           int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

    根据动作how修改或者获取,或者修改并获取当前调用进程的信号掩码(一个信号集)。how有一下值可选:

           SIG_BLOCK
                  将阻塞信号集设置为当前阻塞信号集oldset和指定的信号集的并集,相当于一个或操作

           SIG_UNBLOCK
                  根据设置的信号集set,将当前阻塞信号集oldset对应的位清除,使其不阻塞。

           SIG_SETMASK
                  将阻塞信号集设置为指定信号集set。

    •   如果oldset不为NULL,则函数返回时,oldset指向的内容为调用函数前进程信号掩码,也就是可以获取函数调用之前的信号掩码。
    •   如果set为NULL,则进程信号掩码不会更改,how将被忽略,如果此时oldset不为空,则可以获得之前的信号掩码。

    需要注意的是sigprocmask只对单线程或者单进程有效,多线程中要使用thread_sigmask函数。还有就是SIGSTOP,SIGKILL是不会被阻塞的,即使指定了也会忽略。

      进程中的每个线程都有其各自独立的signal mask。

      子进程会获得父线程同样的signal mask。

    sigpending
    SYNOPSIS
           #include <signal.h>
    
           int sigpending(sigset_t *set);

      sigpending,获得调用进程挂起的信号集,所谓挂起就是指有信号发往这个进程,但是此时被阻塞了,等阻塞解除,就会送至进程里面。

    下面是一个综合的例子(来自APUE):

     1 static void sig_int(int signo)
     2 {
     3     printf("catch SIGINT
    ");
     4     if ( signal(SIGINT, SIG_DFL) == SIG_ERR )
     5     {
     6         perror("signal
    ");
     7     }
     8 }
     9 
    10 int main ( int argc, char *argv[] )
    11 {
    12     sigset_t newset,oldset,pendmask;
    13 
    14     if ( signal(SIGINT,sig_int) == SIG_ERR )
    15     {
    16         perror("signal
    ");
    17     }
    18     
    19     if ( sigemptyset(&newset) < 0 )
    20     {
    21         perror("sigempty
    ");
    22     }
    23 
    24     if ( sigaddset(&newset, SIGINT) < 0 )
    25     {
    26         perror("sigaddset
    ");
    27     }
    28 
    29     if ( sigprocmask(SIG_BLOCK, &newset, &oldset) < 0 )
    30     {
    31         perror("sigprocmask
    ");
    32     }
    33     printf("
    SIGINT block
    ");
    34     
    35     sleep(5);
    36 
    37     if ( sigpending(&pendmask) < 0)
    38     {
    39         perror("sigpending
    ");
    40     }
    41     
    42     if ( sigismember(&pendmask, SIGINT) )
    43     {
    44         printf("SIGINT is pendding
    ");
    45     }
    46 
    47     if ( sigprocmask(SIG_SETMASK, &oldset, NULL) < 0 )
    48     {
    49         perror("sigprocmask
    ");
    50     }
    51     printf("
    SIGINT unblock
    ");
    52     
    53     sleep(5);
    54     return 0;
    55 } 

      在进入第一次睡眠前,设置好了信号掩码,SIGINT将被阻塞,若在唤醒前按下ctrl+c(发送SIGINT),不会进行任何响应,事实上,如果不进行阻塞的话,收到任何信号将会唤醒sleep。等到第二次调用sigprocmask将signal mask恢复,则之前的那个SIGINT就会被响应,再次按下ctrl+c,int立马解除了第二个sleep。

    运行结果:

    SIGINT block
    ^C^C                       <----------此处阻塞了
    SIGINT is pendding
    catch SIGINT
    
    SIGINT unblock
    ^C                         <------------此处立马响应

    并且可以看到,第一次连续发了2个SIGINT但是下面只响应了一次,说明阻塞的信号并不会在一个阻塞队列里面。

  • 相关阅读:
    日常排版--word中的一些小技巧(交叉引用)
    各种中文乱码解决办法
    SpringBoot @RequestBody 中文乱码
    转:十大经典排序算法(动图演示)
    阿里云服务器,无法通过公网ip访问实例
    Attribute meta-data#android.support.VERSION@value value=(25.4.0) from AndroidManifest.xml:25:13-35 is also present at AndroidManifest.xml:28:13-35 value=(26.1.0).
    synchronized用法详解
    错误:(26, 13) Failed to resolve: com.android.support:appcompat-v7:27.+
    HashMap的clear方法
    SSM之全局异常处理器
  • 原文地址:https://www.cnblogs.com/thammer/p/5019781.html
Copyright © 2020-2023  润新知