进程间通信之sigpromask_01<读书笔记>

// - pending signal
      程序中存在关键代码区。当程序处于关键代码区运行时,程序员希望不被收到信号中断关键代码区的执行。
    同时又不允许简单忽略到达的信号,而是待关键代码区执行结束后,再处理接收到的信号。  - sigprocmask 来设置阻止传递的信号


// - 信号的挂起概念
    当信号产生的时候 ,内核会在接收到信号的进程的PCB中设置相关的标志,以表明该进程接收到了信号。之后,该信号对应的信号处理程序
    会被执行,这个执行操作被称之为传递信号。 从信号的产生到信号传递 ,这期间信号所处的状态称为挂起状态(pendding)  
    可以设置选项,以使进程阻塞某个(或某些)特定信号的传递 。 如果进程接收到被阻塞传递的信号,该信号将会一直处于挂起状态,直到进程解除了
    对该信号的阻塞,该信号才能被传递。 每一个进程都有一个信号的掩码,该掩码用来定义被阻塞传递的信号集合。

 

 

// - 相关api
  头文件:#include <signal.h>
     //1.函数原型:int sigemptyset(sigset_t *set);
       功能:清空信号集合*set ,即初始化信号集合*set中的每位置为0
       参数:
       set - 信号集合set
      返回值:
     成功  返回0
     失败或错误  返回-1

 


  //2.函数原型:int sigfillset(sigset_t *set);
   功能:initializes set to full, including all signals. 即将信号集合*set 中的每一位都置为1
   参数:
     set - 信号集合set
   返回值:
   成功: 返回0
   失败或错误 返回 -1


  //3.函数原型:int sigaddset(sigset_t *set , int signum);
   功能:将信号集合*set中对应于信号signum的位置置1
   参数:
   set - 信号集合set
   signum - 信号位置
   返回值:
   成功 返回 0
   失败 返回-1
  //4.函数原型: int sigdelset(sigset_t *set , int signum);
   功能:将信号集合*set中对应于信号signum的位置置0
   参数:
   set - 信号集合set
   signum - 信号位置
   返回值: 成功返回 0 , 失败返回 -1
  
  //5.函数原型: int sigpending(sigset_t *set);
  功能:将正在被阻塞递送的信号记录到*set中
          returns  the set of signals that are pending for delivery
    to the calling thread (i.e., the signals which have been  raised  while
    blocked).  The mask of pending signals is returned in set.
  参数:
   set - 信号集合
  返回值 成功返回0  失败返回-1


  //6.函数原型:int sigismember(const sigset_t *set, int signum);
   功能:若信号集合*set中对应于信号signum的位为1 ,返回真。失败返回假 
   returns 1 if signum is a member of set, 0  if  signum  is
   not a member, and -1 on error.
   参数:
    set - 信号集合
    signum - 信号位置
    返回值:
    成功返回 1 失败返回 0
    
  //7.函数原型: int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
         功能:此函数用来获取和改变调用进程的信号掩码。根据参数how可以分以下几种:SIG_BLOCK、SIG_UNBLOCK、SIG_SETMASK
   It is  used to change the signal mask, the set of currently blocked signals.  The behaviour of the call is dependent on  the  value
   of how, as follows.

   参数:
    how -  信号操作类型
              // - SIG_BLOCK 信号集合掩码被设置为当前的信号集合与*set的并集
           // - sigset_t newmask = 0x4 ,oldmask;
           // - sigprocmask(SIG_BLOCK , newmask,oldmask);
       // -  解析: 假设进程的当前信号集合掩码为0x3(即会阻塞0号跟1号信号的递送),在执行上述的代码后,进程的当前信号集合掩码
       会变成0x7(即进程会阻塞 0 ,1,2号信号递送),而oldmask将等于0x3(旧的信号集合掩码)
           
        // - SIG_UNBLOCK 信号集合掩码被设置为当前的信号集合减去*set中的信号
         // - sigset_t newmask = 0x1 ,oldmask;
         // - sigprocmask(SIG_UNBLOCK , newmask ,oldmask);
       // - 解析:假设进程的当前信号集合掩码为0x3(即:进程会阻塞0 ,1 号信号递送),在执行上述的代码后,进程的当前信号集合
       掩码会变为0x2(即进程会阻塞1号信号的递送),而oldmask将等于0x3(进程的旧的信号集合掩码)
        // - SIG_SETMASK 信号集合掩码被设置为*set
         // - sigset_t newmask = 0x4 , oldmask;
         // - sigprocmask(SIG_SETMASK , &newmask ,&oldmask);
       // - 解析:假设进程的当前信号集合掩码为0x3,执行上述代码 后,进程的当前信号集合掩码会变成0x4,而oldmask将等于0x3(进程的旧信号
       集合掩码)。
    set - 信的信号集合
    oldset - 旧的信号集合
   
  返回值: 成功 返回 0 , 失败或错误返回 -1

 

 


       
eg:
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <unistd.h>

 static void sig_int(int);

 int main(int argc ,char *argv[]){

   struct sigaction act;
   sigset_t newmask ,oldmask ,pendmask;

   if(signal(SIGQUIT , sig_int) == SIG_ERR){
     printf("can't catch SIGQUIT");
     exit(1);
   }
   if(signal(SIGINT , sig_int) == SIG_ERR){
     printf("can't catch SIGINT");
     exit(2);
   }

   sigemptyset(&newmask);
   sigaddset(&act.sa_mask , SIGQUIT);
// Enter Critical Area , block SIGQUIT and save current signal mask
   if(sigprocmask(SIG_BLOCK , &newmask , &oldmask) < 0){
     printf("SIG_BLOCK ERROR");
     exit(4);
   }

   sleep(15);  // Crtical Area Code here , and SIGQUIT will remain pending
   if(sigpending(&pendmask) < 0){
     printf("sigpending error");
     exit(5);
   }

   if(sigismember(&pendmask , SIGQUIT)){
     printf("\nSIGQUIT pending \n");
   }
//  Exit Critical Area , reset signal mask which unblocks SIGUIT
   if(sigprocmask(SIG_SETMASK , &oldmask , NULL) < 0){
     printf("SIG_SETMASK error");
     exit(6);
   }
   printf("SIGQUIT unblocked \n");
   sleep(100);

   return 0;
 }


 static void sig_int(int signo){ // argument is signal number
   int i ;
   if(signo == SIGINT){
     printf("received SIGINT \n");
     for(i = 1000000000 ; i > 0 ; i--)
       ;
       printf("processed SIGINT \n");

   }else if(signo == SIGQUIT){
     printf("caught SIGQUIT\n");
   }else{
     printf("received signal %d \n" , signo);
   }
   return ;
 }
  

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值