Skip to content

Latest commit

 

History

History
125 lines (99 loc) · 2.61 KB

信号的屏蔽与阻塞.md

File metadata and controls

125 lines (99 loc) · 2.61 KB

信号的屏蔽与阻塞总结

关于Sigprocmask()函数

sigprocmask(int how, const sigset_t *new_set, const sigset_t *old_set);

how有三种参数:

  • SIG_BLOCK
  • SIG_UNBLOCK
  • SIG_SETMASK

两种实现信号的屏蔽与阻塞的方法:

法一:SIG_BLOCK, SIG_UNBLOCK成对出现

法二:SIG_BLOCK, SIG_SETMASK成对出现

原理:

​ 在二者中间运行的代码,如果有kill或其它函数传递信号进来,将一律将new_set集合中的信号堵在外面,达到屏蔽信号的效果;

对于屏蔽的信号如何处理:

在信号屏蔽过程中出现的所有信号,不管发来了多少次,在解除屏蔽后,都将执行且

仅执行一次

以下是经典例子:

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

//定义三个handler信号处理函数
static void sig_usr1(int signo)
{
  printf("SIGUSR1 function\n");
}
static void sig_usr2(int signo)
{
  printf("SIGUSR2 function\n");
}

static void sig_int(int signo)
{
  printf("SIGINT function\n");
}

//取代signal(num, handler)函数
void sig_catch(int sig_no, void (*f)(int))
{
    struct sigaction sa;
    sa.sa_handler = f;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sigaction(sig_no, &sa, (struct sigaction *) 0);
}


int main()
{
  sigset_t newmask,oldmask;

  sig_catch(SIGUSR1,sig_usr1);
  sig_catch(SIGUSR2,sig_usr2);
  sig_catch(SIGINT,sig_int);

//  signal(SIGUSR1,sig_usr1);
//  signal(SIGUSR2,sig_usr2);
//  signal(SIGINT,sig_int);

  //这里仅将SIGUSR1, SIGUSR2放入信号集合中
  sigemptyset(&newmask);
  sigaddset(&newmask,SIGUSR1);
  sigaddset(&newmask,SIGUSR2);

  //信号阻塞开始
  sigprocmask(SIG_BLOCK,&newmask,&oldmask);
  printf("SIGUSR is blocked\n");

  //传来一堆信号
  kill(getpid(),SIGUSR2);
  kill(getpid(),SIGUSR1);
  kill(getpid(),SIGUSR2);
  kill(getpid(),SIGUSR1);
  kill(getpid(),SIGUSR2);
  kill(getpid(),SIGINT);
    
  //分别用两种方法实现解除信号的阻塞  
  
  printf("=======\n");
  printf("SIGUSR is unblocked\n");
       
  //方法一
  sigprocmask(SIG_UNBLOCK,&newmask,NULL);

  //方法二
  sigprocmask(SIG_SETMASK,&oldmask,NULL);

  return 0;
}

执行结果:

SIGUSR is blocked		//开始信号阻塞
SIGINT function  	//SIGINT不在集合中,可以被接收到
=======
SIGUSR is unblocked		//解除信号阻塞
SIGUSR1 function	//解除阻塞后,依次接收到两个信号,有且仅执行一次
SIGUSR2 function
    
/* 注意点:
SIGUSR1和SIGUSR2是系统内置的宏,在signal.h中
有且仅有这两个可以用户自定义