阻塞信号的相关概念

本文详细阐述了操作系统中信号的递达、未决状态、阻塞和信号集操作,包括sigemptyset、sigfillset、sigaddset等函数的用法,以及sigprocmask和sigpending在管理信号屏蔽字和查看未执行信号中的应用。
摘要由CSDN通过智能技术生成

一.信号其他相关常见概念

1.实际执行信号的处理动作称为信号递达 (Delivery)
2.信号从产生到递达之间的状态 , 称为信号未决 (Pending)
3.进程可以选择阻塞 (Block ) 某个信号。
4/被阻塞的信号产生时将保持在未决状态 , 直到进程解除对此信号的阻塞 , 才执行递达的动作 .
注意 , 阻塞和忽略是不同的 , 只要信号被阻塞就不会递达 , 而忽略是在递达之后可选的一种处理动作。

2. 在内核中的表示
信号在内核中的表示示意图
block:信号有无被堵塞,1表示被堵塞,0表示未被堵塞
pending:表示该进程有无接受到这个信号,1表示接受到这个信号,0表示为接受到这个信号
handler: 信号的处理方法SIL_DFL代表默认处理方法,SIG_IGN代表忽略该信号,User Space代表用户自定义的方法
3. sigset_t
sigset_t是操作系统定时的一种数据结构(本质是位图),与上图的block 和 spending相对应sigset_t做前者被称为 信号屏蔽字,做后者被称为信号集
4. 信号集操作函数
sigset_t 类型对于每种信号用一个 bit 表示 有效 无效 状态 , 至于这个类型内部如何存储这些 bit则依赖于系统实现 , 从使用者的角度是不必关心的 , 使用者只能调用以下函数来操作 sigset_ t 变量 ,而不应该对它的内部数据做任何解释 , 比如用 printf 直接打印 sigset_t 变量是没有意义的
#include <signal.h>
int sigemptyset(sigset_t *set);

作用:函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含 任何有效信号

返回值:成功返回0,失败返回-1,并设置相关错误码

int sigfillset(sigset_t *set);
作用:
函数 sigfillset 初始化 set 所指向的信号集 , 使其中所有信号的对应 bit 置位 ,表示 该信号集的有效信号包括系统支持的所有信号。
返回值:成功返回0,失败返回-1,并设置相关错误码
int sigaddset (sigset_t *set, int signo);
作用:添加有效信号
返回值: 成功返回0,失败返回-1,并设置相关错误码
int sigdelset(sigset_t *set, int signo);
作用:删除有效信号
返回值: 成功返回0,失败返回-1,并设置相关错误码
int sigismember const sigset_t *set, int signo);
作用:查找set中是否有相关的信号
返回值:有相关信号返回1,没有相关信号返回0,查找失败返回-1,并设置相关的错误码
5.信号屏蔽字的设置
sigprocmask函数
原型:
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
参数:
how :处理模式,有三种
set:设置堵塞时的参考数据
oset:输出型参数,可以获取修改之前的堵塞表,如果置为nullptr则代表忽略原本数据
 注意:9号信号是不能被设置为堵塞状态,也不能被用户自定义
6.未执行信号查看

#include <signal.h>

       int sigpending(sigset_t *set);

作用:读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1,并设置相关的错误码

参数:

set:输出型参数该函数会把未执行的信号集存储到set中。

上述所有函数在代码中的使用如下:

#include <csignal>
#include <iostream>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>


int main()
{
    // 先定义一个被系统调用接口需要的数据类型
    sigset_t set;
    sigset_t set1;
    // 初始化变量,是其中的相关数值明确(本次初始化把所有存在标志全部置为无)
    int n = sigemptyset(&set);
    assert(n != -1);
    // 对该变量中插入相关变量
    n = sigaddset(&set, 2);
    assert(n != -1);
    n = sigaddset(&set, 3);
    assert(n != -1);
    // 删除该变量中的相关信号
    n = sigdelset(&set, 3);
    assert(n != -1);
    // 设置相关的堵塞(这里我们选择覆盖模式,即新的set覆盖老的set,第三个参数置为空,即对老的set忽视)
    n = sigprocmask(SIG_SETMASK, &set, nullptr);
    assert(n != -1);
    // 获取为被执行的信号集,并且循环查看
    while (true)
    {
        sigemptyset(&set1);
        n = sigpending(&set1);
        assert(n != -1);
        for(int i=0;i<=31;i++)
        {
            if(sigismember(&set1,i)==1)
            std::cout<<1;
            else
            std::cout<<0;
        }
        std::cout<<"我的pid:"<<getpid();
        std::cout<<std::endl;
        sleep(1);
    }
}

运行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值