信号集(未决信号集,阻塞信号集)

        未决信号集和阻塞信号集的关系

        阻塞信号集是当前进程要阻塞的信号的集合,未决信号集是当前进程中还处于未决状态的信号的集合,这两个集合存储在内核的PCB中。

  • 下面以SIGINT为例说明信号未决信号集和阻塞信号集的关系:
  •         当进程收到一个SIGINT信号(信号编号为2),首先这个信号会保存在未决信号集合中,此时对应的2号编号的这个位置上置为1,表示处于未决状态;在这个信号需要被处理之前首先要在阻塞信号集中的编号为2的位置上去检查该值是否为1:
    •         如果为1,表示SIGNIT信号被当前进程阻塞了,这个信号暂时不被处理,所以未决信号集  上该位置上的值保持为1,表示该信号处于未决状态;
      •         如果为0,表示SIGINT信号没有被当前进程阻塞,这个信号需要被处理,内核会对SIGINT信号进行处理(执行默认动作,忽略或者执行用户自定义的信号处理函数),并将未决信号集中编号为2的位置上将1变为0,表示该信号已经处理了,这个时间非常短暂,用户感知不到。
        •         当SIGINT信号从阻塞信号集中解除阻塞之后,该信号就会被处理。

 

 

信号集相关函数       

  • int sigemptyset(sigset_t *set);

函数说明:将某个信号集清0  

函数返回值:成功:0;失败:-1,设置errno

  • int sigfillset(sigset_t *set);

函数说明:将某个信号集置1   

函数返回值:成功:0;失败:-1,设置errno

  • int sigaddset(sigset_t *set, int signum);

函数说明:将某个信号加入信号集合中

函数返回值:成功:0;失败:-1,设置errno

  • int sigdelset(sigset_t *set, int signum);

函数说明:将某信号从信号清出信号集   

函数返回值:成功:0;失败:-1,设置errno

  • int sigismember(const sigset_t *set, int signum);

函数说明:判断某个信号是否在信号集中

函数返回值:在:1;不在:0;出错:-1,设置errno

  • sigprocmask函数

        函数说明:用来屏蔽信号、解除屏蔽也使用该函数。其本质,读

        取或修改进程控制块中的信号屏蔽字(阻塞信号集)。

        特别注意,屏蔽信号只是将信号处理延后执行(延至解除屏蔽);而忽略表示将信号丢弃处理。

        函数原型:int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

        函数返回值:成功:0;失败:-1,设置errno

        函数参数:how参数取值:假设当前的信号屏蔽字为mask

        SIG_BLOCK: 当how设置为此值,set表示需要屏蔽的信号。

        SIG_UNBLOCK: 当how设置为此,set表示需要解除屏蔽的信号。

        set:传入参数,是一个自定义信号集合。由参数how来指示如何修改当前信号屏蔽字

        oldset:传出参数,保存旧的信号屏蔽字。

  • sigpending函数

        函数原型:int sigpending(sigset_t *set);    

        函数说明:读取当前进程的未决信号集函数参数:set传出参数

        函数返回值:成功:0;失败:-1,设置errno

 练习:编写程序,设置阻塞信号集并把所有常规信号的未决状态打印至屏幕(以二号和三号信号为例)

        

#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
using namespace std;

//信号处理函数
void sighandler(int signo)
{
        cout << "signo==[" << signo << "]" << endl;
}

int main()
{

        //注册SIGINT和SIGQUIT的信号处理函数
        signal(SIGINT, sighandler);//2 ctrl+c
        signal(SIGQUIT, sighandler);//3 ctrl+/

        //定义sigset_t类型的变量
        sigset_t pending, mask, oldmask;

        //初始化
        sigemptyset(&pending);
        sigemptyset(&mask);
        sigemptyset(&oldmask);

        //将SIGINT和SIGQUIT加入到阻塞信号集中
        sigaddset(&mask, SIGINT);
        sigaddset(&mask, SIGQUIT);

        //将mask中的SIGINT和SIGQUIT信号加入到阻塞信号集中
        //sigprocmask(SIG_BLOCK, &mask, NULL);
        sigprocmask(SIG_BLOCK, &mask, &oldmask);

        int i = 1;
        int k = 1;
        while(1)
        {
                //获取未决信号集
                sigpending(&pending);

                for(i=1; i<32; i++)
                {
                        //判断某个信号是否在集合中
                        if(sigismember(&pending, i)==1)
                        {
                                cout << "1";
                        }
                        else
                        {
                                cout << "0";
                        }
                }
                cout << endl;

                if(k++%10==0)
                {
                        //从阻塞信号集中解除对SIGINT和SIGQUIT的阻塞
                        //sigprocmask(SIG_UNBLOCK, &mask, NULL);        
                        sigprocmask(SIG_SETMASK, &oldmask, NULL);
                }
                else
                {
                        sigprocmask(SIG_BLOCK, &mask, NULL);
                }

                sleep(1);
        }

        return 0;
}

结果如下:

        

 产生信号后就被阻塞,然后被打印出来1

  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信号处理是Linux系统中的一个重要概念,用于处理进程间通信和异常情况。信号是由操作系统或其他进程发送给进程的通知,用于通知进程发生了某个事件或异常情况。信号可以被进程捕获和处理,也可以被忽略或使用默认处理方式。 在Linux中,信号可以由多种情况触发,比如按下CTRL+C键产生的SIGINT信号,非法内存访问产生的信号,硬件故障产生的信号,以及环境切换等。进程可以通过调用signal函数来注册信号处理函数,以捕获和处理特定的信号。 signal函数的原型如下: ```c typedef void (*sighandler)(int); sighandler signal(int signum, sighandler handler); ``` 其中,signum是需要处理的信号编号,handler是信号的处理函数。处理函数可以是用户自定义的函数,也可以是预定义的常量SIG_IGN表示忽略该信号,或者SIG_DFL表示使用默认的信号处理方式。 在信号处理函数中,可以执行一些特定的操作来处理信号,比如打印日志、保存数据、发送信号给其他进程等。处理函数可以是空函数,表示仅仅捕获信号但不做任何处理。 需要注意的是,一个进程可以屏蔽掉大多数的信号,除了SIGSTOP和SIGKILL这两个信号是无法被屏蔽的。信号有优先级,当一个进程有多个未决信号时,内核将按照发送的顺序来递送信号。值越小的信号越先被递送。 在Linux中,可以通过编写信号处理程序来处理不同的信号,并根据需要执行特定的操作。通过信号处理,可以实现进程间通信、优雅地关闭进程或处理异常情况等功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值