信号sigprocmask函数

 

#include <signal.h>
int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
返回值:若成功则返回0,若出错则返回-1

首先,若oset是非空指针,那么进程的当前信号屏蔽字通过oset返回。

其次,若set是一个非空指针,则参数how指示如何修改当前信号屏蔽字。

 

how说明
 SIG_BLOCK该进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集的并集。set包含了我们希望阻塞的附加信号
 SIG_UNBLOCK该进程新的信号屏蔽字是其当前信号屏蔽字和set所指向信号集补集的交集。set包含了我希望解除阻塞的信号
 SIG_SETMASK该进程新的信号屏蔽字将被set指向的信号集的值代替


如果set是空指针,则不改变该进程的信号屏蔽字,how的值也无意义。

 

直接通过代码

#include <stdio.h> 
#include <stdlib.h> //malloc 
#include <unistd.h> 
#include <signal.h> 
//信号处理函数 
void sig_quit(int signo)
{   
    printf("收到了SIGQUIT信号!\n");
	sigset_t set;
	sigemptyset(&set);
    sigprocmask(SIG_BLOCK,NULL,&set);
    //当前捕获信号在被捕获期间是被阻塞的.
	if(sigismember(&set,SIGQUIT))  //测试一个指定的信号位是否被置位(为1),测试的是newmask     
    {
        printf("捕获期间旧SIGQUIT信号被屏蔽了!\n");
    }
    else
    {
        printf("捕获期间旧SIGQUIT信号没有被屏蔽!!!!!!\n");
    }
    //在设置回默认
    if(signal(SIGQUIT,SIG_DFL) == SIG_ERR)
    {
        printf("无法为SIGQUIT信号设置缺省处理(终止进程)!\n");
        exit(1);
    }
}

int main(int argc, char *const *argv)
{
    sigset_t newmask,oldmask,pendmask; 
    if(signal(SIGQUIT,sig_quit) == SIG_ERR)  //注册信号对应的信号处理函数,"ctrl+\"     
    {        
        printf("无法捕捉SIGQUIT信号!\n");
        exit(1);   
        //退出程序,参数是错误代码,0表示正常退出,非0表示错误,但具体什么错误,没有特别规定     
    }

    sigemptyset(&newmask); //newmask信号集中所有信号都清0(表示这些信号都没有来)
    sigaddset(&newmask,SIGQUIT); //设置newmask信号集中的SIGQUIT信号位为1,也就是说,再来SIGQUIT信号时,进程就收不到,设置为1就是该信号被阻塞掉    
    
    printf("我要开始休息10秒了--------begin--\n");
    sleep(10);   //测试没有屏蔽的时候处理信号   
    printf("我已经休息了10秒了--------end----!\n");
    //再次注册
    if(signal(SIGQUIT,sig_quit) == SIG_ERR)  //注册信号对应的信号处理函数,"ctrl+\"     
    {        
        printf("无法捕捉SIGQUIT信号!\n");
        exit(1);   
        //退出程序,参数是错误代码,0表示正常退出,非0表示错误,但具体什么错误,没有特别规定     
    }
    if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0)  //第一个参数用了SIG_BLOCK表明设置 进程 新的信号屏蔽字 为 “当前信号屏蔽字 和 第二个参数指向的信号集的并集     
    {                                                 
        //一个 ”进程“ 的当前信号屏蔽字,刚开始全部都是0的;所以相当于把当前 "进程"的信号屏蔽字设置成 newmask(屏蔽了SIGQUIT);   
        //第三个参数不为空,则进程老的(调用本sigprocmask()之前的)信号集会保存到第三个参数里,用于后续,这样后续可以恢复老的信号集给线程         
        printf("sigprocmask(SIG_BLOCK)失败!\n");
        exit(1);
    }
    if(sigismember(&oldmask,SIGQUIT))  //测试一个指定的信号位是否被置位(为1),测试的是newmask     
    {
        printf("旧SIGQUIT信号被屏蔽了!\n");
    }
    else
    {
        printf("旧SIGQUIT信号没有被屏蔽!!!!!!\n");
    }
	
    printf("我再次要开始休息10秒了--------begin--,此时我无法接收SIGQUIT信号!\n");
    sleep(10);   //设置阻塞SIGQUIT,无法收到SIGQUIT信号;     
    printf("我再次已经休息了10秒了--------end----!\n");
    if(sigismember(&newmask,SIGQUIT))  //测试一个指定的信号位是否被置位(为1),测试的是newmask     
    {
        printf("SIGQUIT信号被屏蔽了!\n");
    }
    else
    {
        printf("SIGQUIT信号没有被屏蔽!!!!!!\n");
    }
    if(sigismember(&newmask,SIGHUP))  //测试另外一个指定的信号位是否被置位,测试的是newmask     
    {
        printf("SIGHUP信号被屏蔽了!\n");
    }
    else
    {
        printf("SIGHUP信号没有被屏蔽!!!!!!\n");
    }
    sigpending(&pendmask); //检查信号是悬而未决的
    if(sigismember(&pendmask,SIGQUIT)) //SIGQUIT 是悬而未决的。所谓悬而未决,是指SIGQUIT被阻塞还没有被处理
          printf("SIGQUIT pending\n");
    //把信号集还原回去,之前被阻塞住的信号会再次得到处理,但是就算之前捕获了多次也只会触发一次信号处理函数     
    if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0)  //第一个参数用了SIGSETMASK表明设置进程新的信号屏蔽字为第二个参数指向的信号集,第三个参数没用     
    {
        printf("sigprocmask(SIG_SETMASK)失败!\n");
        exit(1);
    }

    printf("sigprocmask(SIG_SETMASK)成功!\n");
    
    if(sigismember(&oldmask,SIGQUIT))  //测试一个指定的信号位是否被置位,这里测试的当然是oldmask     
    {
        printf("SIGQUIT信号被屏蔽了!\n");
    }
    else
    {
        printf("SIGQUIT信号没有被屏蔽,您可以发送SIGQUIT信号了,我要sleep(10)秒钟!!!!!!\n");
        int mysl = sleep(10);
        if(mysl > 0)
        {
            printf("sleep还没睡够,剩余%d秒\n",mysl);
        }
    }
    printf("end main!\n");
    return 0;
}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值