zoukankan      html  css  js  c++  java
  • 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但是下面只响应了一次,说明阻塞的信号并不会在一个阻塞队列里面。

  • 相关阅读:
    HearthBuddy投降插件2019-11-01的使用
    正则表达式在线分析 regex online analyzer
    Tips to write better Conditionals in JavaScript
    The fileSyncDll.ps1 is not digitally signed. You cannot run this script on the current system.
    Cannot capture jmeter traffic in fiddler
    JMETER + POST + anti-forgery token
    input type color
    HearthBuddy修改系统时间
    What are all the possible values for HTTP “Content-Type” header?
    UDK性能优化
  • 原文地址:https://www.cnblogs.com/thammer/p/5019781.html
Copyright © 2011-2022 走看看