C语言学习:信号屏蔽字sigset_t,sigprocmask,sigpending

C语言学习:信号屏蔽字


简介:
之前在学习sigsetjmp和siglongjmp的时候说过信号屏蔽字的相关东西,在很早之前的关于signal的学习中也讲过信号屏蔽字,所以在这里单独进行总结一下,因为有时候信号相关的处理在程序中还是比较重要的。
定义:什么是信号屏蔽字??

信号屏蔽字就是进程中被阻塞的信号集, 这些信号不能发送给该进程, 它们在该进程中被”屏蔽”了. 但是实际上它们是被阻塞了.

线程信号量的相关讲解


提示:

博客:章飞_906285288
博客地址:http://blog.csdn.net/qq_29924041


关于信号屏蔽函数sigprocmask

 //要包含的头文件
 #include <signal.h>
 int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
返回:成功返回0,失败返回-1
参数列表:
how:修改信号屏蔽字的方式
set:这个信号集设为新的当前信号屏蔽字. 如果为NULL则不改变.
oldset:保存进程旧的信号屏蔽字. 如果为NULL则不保存

以下是how的三种方式:
1:SIG_BLOCK:该进程的信号屏蔽字是当前屏蔽字和set指向的屏蔽字的并集
2:SIG_UNBLOCK:该进程的信号屏蔽字是当前屏蔽字和set指向的屏蔽字的补集的交集
3:SIG_SETMASK:该进程的信号屏蔽字要被set指向的信号屏蔽字代替

注意:sigprocmask仅仅只是对于单线程而言的,对于多线程的话,可能就需要使用pthread_sigmask了

当然在使用sigprocmask函数之前,有几个函数是是必不可少的

   #include <signal.h>

   int sigemptyset(sigset_t *set);
   返回:成功返回0,失败返回-1
   功能:将信号集合清空,并且初始化       

   int sigfillset(sigset_t *set);
   返回:成功返回0,失败返回-1
   功能:参数set信号集初始化,然后把所有的信号加入到此信号集里即将所有的信号标志位置为1,屏蔽所有的信号

   int sigaddset(sigset_t *set, int signum);
   返回:成功返回0,失败返回-1
   功能:将要屏蔽的型号加入到信号屏蔽集里去

   int sigdelset(sigset_t *set, int signum);
   返回:成功返回0,失败返回-1
   功能:功能是用来将参数signum代表的信号从参数set信号集里删除

   int sigismember(const sigset_t *set, int signum);
   返回:成功返回0,失败返回-1
   功能:sigismember()用来测试参数signum 代表的信号是否已加入至参数set信号集里    

信号屏蔽集sigset_t

typedef struct {
    unsigned long sig[_NSIG_WORDS];
} sigset_t

信号集被定义为一种数据类型。从上面可以看出,其实信号集的结构体中只是个无符号长整形的数组。


获取未处理的信号屏蔽集合

当调用信号屏蔽的相关函数后,被屏蔽的信号对于调用进程来说是阻塞的,不能发送给进程的,可以通过sigpending将所有的信号屏蔽集给取出来。
函数:sigpending;

#include<signal.h>
int sigpending(sigset_t *set);
成功返回0,失败则需要返回-1

测试代码

/*
 * ===========================================================================
 *
 *       Filename:  sigmask.c
 *    Description:  关于信号屏蔽字
 *        Version:  1.0
 *        Created:  2017年07月27日 22时28分49秒
 *       Revision:  none
 *       Compiler:  gcc
 *         Author:   (), 
 *        Company:  
 *
 * ===========================================================================
 */

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



void signal_handler(int signo){

  printf("signo:%d\n",signo);

}

int main(int argc,char *argv[]){
 sigset_t old_sig_set,new_sig_set,suspend_sig_set;

  if(signal(SIGINT,signal_handler) == SIG_ERR){
    printf("signal SIGINT error\n");
    exit(-1);
  }

  if(signal(SIGQUIT,signal_handler) == SIG_ERR){
    printf("signal SIGQUIT error\n");
    exit(1);
  }

 //将信号集清空并且初始化
 if(sigemptyset(&old_sig_set) != 0){
   printf("sigemptyset old_sig_set error\n");
 }
 if(!sigemptyset(&new_sig_set) != 0){
   printf("sigemptyset new_sig_set error\n");
 }
 if(!sigemptyset(&suspend_sig_set) != 0){
   printf("sigemptyset suspend_sig_set error\n");
 }

 //将SIGQUIT添加进old_sig_set信号屏蔽集中去,当前set指向的是SIGQUIT
  if(sigaddset(&new_sig_set,SIGQUIT) != 0){
    printf("sigaddset old_sig_set error\n");
  }

  //调用sigprocmask来实现对信号的屏蔽
  //SIG_BLOCK:该进程屏蔽字是当前的屏蔽字和set指向的屏蔽字的并集
  //SIG_UNBLOCK 该进程的信号屏蔽字与set指向的信号屏蔽字的补集的交集
  //SIG_SETMASK,该进程的信号屏蔽字要被set指向的信号屏蔽代替


  //将进程旧的屏蔽字保存到old_sig_set中
  if(sigprocmask(SIG_BLOCK,&new_sig_set,&old_sig_set) != 0){
    printf("sigprocmask old_sig_set error\n");
    exit(0);
  }

  printf("SIGQUIT BLOCK\n");
  printf("please enter ctrl + \\");

  //睡眠10秒,在这10秒内按ctrl+\是没有相应的
  sleep(10);


  //获取未处理的信号屏蔽集合
  if(!sigpending(&suspend_sig_set) < 0){
    printf("sigpending error\n");
  }

  //用来测试参数SIGQUIT代表的信号是否已经加入到参数set中去
  if (sigismember(&suspend_sig_set,SIGQUIT) != 0){
     printf("sigismember error\n");
  }else{
    printf("SIGQUIT PENDING\n");
  }

  //从信号屏蔽集中恢复SIGQUIT,或者使用SIGDELSET来进行恢复
  if(sigprocmask(SIG_SETMASK,&old_sig_set,NULL) < 0){
    printf("sigprocmask restore error\n");
  }else{
    printf("SIGQUIT UNBLOCK \n");
  }

//或者使用setdelset进行信号屏蔽字的删除操作
//if(sigdelset(&new_sig_set,SIGQUIT) == 0){                                       
//                                                                             
//}  


  sleep(10);
  return 0;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值