zoukankan      html  css  js  c++  java
  • 【C】——sigprocmask 阻塞进程信号

    1、有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延时一段时间去调用信号处理函数。这种情况是通过阻塞信号实现的。

     

    2、信号阻塞和忽略信号的区别。

    阻塞的概念和忽略信号是不同的。操作系统在信号被进程解除阻塞之前不会讲信号传递出去,被阻塞的信号也不会影响进程的行为,信号只是暂时被阻止传递。当进程忽略一个信号时,信号会被传递出去但进程会将信号丢弃。

     

    3、信号阻塞系统调用,它们的都起到阻塞的作用,它们不是协作使用的。

    1. #include <signal.h>  
    2.   
    3. int sigprocmask(ubt how,const sigset_t*set,sigset_t *oldset);  
    4.   
    5. int sigsuspend(const sigset_t*sigmask);  

    sigprocmask设定对信号屏蔽集内的信号的处理方式(阻塞或不阻塞)。


    参数:

    how:用于指定信号修改的方式,可能选择有三种

    SIG_BLOCK//将set所指向的信号集中包含的信号加到当前的信号掩码中。即信号掩码和set信号集进行或操作。

    SIG_UNBLOCK//将set所指向的信号集中包含的信号从当前的信号掩码中删除。即信号掩码和set进行与操作。

    SIG_SETMASK //将set的值设定为新的进程信号掩码。即set对信号掩码进行了赋值操作。

     

    set:为指向信号集的指针,在此专指新设的信号集,如果仅想读取现在的屏蔽值,可将其置为NULL。

    oldset:也是指向信号集的指针,在此存放原来的信号集。可用来检测信号掩码中存在什么信号。

    返回说明:

    成功执行时,返回0。失败返回-1,errno被设为EINVAL。

    sigprocmask示例(演示添加信号掩码):

     1 #include <stdio.h>
     2 #include <signal.h>
     3 void checkset();
     4 
     5 void main()
     6 {
     7      sigset_tblockset;
     8      sigemptyset(&blockset);
     9      sigaddset(&blockset,SIGINT);
    10      sigaddset(&blockset,SIGTSTP);
    11 
    12     &nbsp;checkset();
    13 
    14      sigprocmask(SIG_SETMASK,&blockset,NULL);
    15      checkset();
    16 
    17    &nbsp; sigaddset(&blockset,SIGTERM);
    18      sigprocmask(SIG_BLOCK,&blockset,NULL);
    19      checkset();
    20 
    21      sigdelset(&blockset,SIGTERM);
    22      sigprocmask(SIG_UNBLOCK,&blockset,NULL);
    23      checkset();
    24 }
    25 
    26 void checkset()
    27 {
    28 
    29      sigset_tset set;
    30      printf("checksetstart:
    ");
    31 
    32      if(sigprocmask(0,NULL,&set)<0)
    33      {
    34      printf("checksetsigprocmask error!!
    ");
    35      exit(0);
    36      }
    37 
    38      if(sigismember(&set,SIGINT))
    39      printf("sigint
    ");
    40      if(sigismember(&set,SIGTSTP))
    41      printf("sigtstp
    ");
    42 
    43      if(sigismember(&set,SIGTERM))
    44      printf("sigterm
    ");
    45       printf("checksetend
    ");
    46 }

     

    sigprocmask示例(演示添某部分代码不被信号打搅):

     1 #include <stdio.h>
     2 #include <signal.h>
     3 void checkset();
     4 
     5 void func();
     6 void main()
     7 {
     8      sigset_tblockset,oldblockset,pendmask;
     9      printf("pid:%ld
    ",(long)getpid());
    10 
    11      signal(SIGINT,func); //信号量捕捉函数,捕捉到SIGINT,跳转到函数指针func处执行
    12 
    13     sigemptyset(&blockset); //初始化信号量集
    14     sigaddset(&blockset,SIGTSTP); //将SIGTSTP添加到信号量集中
    15    &nbsp;sigaddset(&blockset,SIGINT);//将SIGINT添加到信号量集中
    16 
    17    sigprocmask(SIG_SETMASK,&blockset,&oldblockset); //将blockset中的SIGINT,SIGTSTP阻塞掉,并保存当前信号屏蔽字
    18 
    19      /*执行以下程序时,不会被信号打搅*/
    20     checkset();
    21    &nbsp;sleep(5);
    22      sigpending(&pendmask); //检查信号是悬而未决的
    23      if(sigismember(&pendmask,SIGINT)) //SIGINT是悬而未决的。所谓悬而未决,是指SIGQUIT被阻塞还没有被处理
    24          printf("SIGINTpending
    ");
    25 
    26      /*免打搅结束*/
    27 
    28      sigprocmask(SIG_SETMASK,&oldblockset,NULL); //恢复被屏蔽的信号SIGINT SIGTSTP
    29      printf("SIGINTunblocked
    ");
    30      sleep(6);
    31 }
    32 
    33 void checkset()
    34 {
    35      sigset_tset;
    36      printf("checksetstart:
    ");
    37      if(sigprocmask(0,NULL,&set)<0)
    38      {
    39      printf("checksetsigprocmask error!!
    ");
    40      exit(0);
    41      }
    42      if(sigismember(&set,SIGINT))
    43      printf("sigint
    ");
    44 
    45      if(sigismember(&set,SIGTSTP))
    46      printf("sigtstp
    ");
    47 
    48      if(sigismember(&set,SIGTERM))
    49      printf("sigterm
    ");
    50 
    51 &nbsp;    printf("checksetend
    ");
    52 
    53 }
    54 void func()
    55 {
    56      printf("hellofunc
    ");
    57 }

     sigeprocmask函数通常和sigemptyset、sigfillset、sigaddset、sigdelset、 sigismember函数配合使用,主要有两种用途:

    1.我们不希望某些不太重要的信号来影响我们的进程,我们就可以把这些信号添加到信号屏蔽集中。使它们不打扰进程的执行。

    2.如果系统现在很忙,没有时间及时相应信号,进程可以先把信号阻塞掉,等系统有空闲时间在去相应,这也保证了信号的可靠性。

    例二:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<signal.h>
     4 
     5 sigset_t newmask,oldmask,pendmask;
     6 
     7 void sig_usr(int signo)
     8 {
     9     printf("this is sig_usr!
    ");
    10 
    11 }
    12 
    13 int main(int argc, char *argv[])
    14 {
    15 
    16     if(signal(SIGUSR1,sig_usr) == SIG_ERR){
    17         printf("signal error!
    ");
    18         exit(1);
    19     }
    20 
    21     sigemptyset(&newmask);
    22     sigaddset(&newmask,SIGUSR1);
    23     if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0){
    24         printf("sig_block error!
    ");
    25         exit(1);
    26     }
    27 
    28     printf("first raise(SIGUSR1)!
    ");
    29     raise(SIGUSR1);
    30     if(sigpending(&pendmask) < 0){
    31         printf("sigpending error!
    ");
    32         exit(1);
    33     }
    34 
    35     if(sigismember(&pendmask, SIGUSR1))
    36         printf("sigusr1 pending!
    ");
    37 
    38     if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){
    39         printf("sig_setmask error!
    ");
    40         exit(1);
    41     }
    42 
    43     printf("second raise(SIGUSR1)!
    ");
    44     raise(SIGUSR1);
    45 
    46     printf("main end!
    ");
    47     exit(0);
    48 }

    结果如下:

    如果注释掉下面的代码

    1      if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){
    2          printf("sig_setmask error!
    ");
    3          exit(1);
    4      }

    结果如下:

    发现第一次发送的信号也不会处理了。笔者也不知道为什么会发生这种情况,还是下次写代码的时候注意一下,阻塞完信号,处理的时候要及时恢复好了!

    若只注释掉下面的代码:

    1      if(sigpending(&pendmask) < 0){
    2          printf("sigpending error!
    ");
    3          exit(1);
    4      }
    5  
    6      if(sigismember(&pendmask, SIGUSR1))
    7          printf("sigusr1 pending!
    ");

    而留下:

    1       if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){
    2           printf("sig_setmask error!
    ");
    3           exit(1);
    4       }

    结果第一次发送的信号也会有响应,截图如下:

    看来在阻塞信号的时候接收到了信号,当恢复信号屏蔽字的时候信号也会得到处理!

  • 相关阅读:
    es 报错cannot allocate because allocation is not permitted to any of the nodes
    linux下获取软件源码包 centos/redhat, debian/ubuntu
    windows假死原因调查
    k8s-calico
    helm使用
    docker网络模式
    4、formula 法则、原则、数学公式
    powershell自动添加静态IP
    WDS部署Windows server2012初试
    2、puppet资源详解
  • 原文地址:https://www.cnblogs.com/ngnetboy/p/3377630.html
Copyright © 2011-2022 走看看