前两天写了信号的基本概念以及如何去产生信号,欢迎大家戳博客链接:https://blog.csdn.net/apt1203JN/article/details/79955014
先来了解一下信号的三种状态:

* 信号递达(Delivery):实际执行信号的处理动作
* 信号未决(Pending):信号从产生到递达之间的状态
* 信号阻塞(Block):进程可以选择阻塞某个信号,被阻塞的信号产生时将保持在未决状态,直到进程接触对此信号的阻塞,才执行递达的动作

注意阻塞和忽略的不同之处:

* 阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在抵达之后可选的一种处理动作

下面来看一下操作系统为每个进程提供的一套信号机制:

上图的三张表分别为:阻塞表(Block)、未决表(Pending)、递达表
这三张表分别对应三种不同的状态:信号阻塞、信号未决、信号递达之后的自定义捕捉
前两张表都是通过位图来存储的(决定了当前是否能收到信号),信号被阻塞就将相应位置置1,否则就置0。而在pending表中,当前位是1时表示信号存在,置0时表不存在。(pending表中的数据是判断信号是否存在的重要因素)

在上图当中:

SIGHUP信号(也就是(1)号信号)未阻塞也未产生过,当它抵达时执行默认处理工作。
SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。
SIGQUIT信号从未产生过,一旦产生,SIGQUIT信号将被阻塞,它的处理动作是用户自定义的函数singhandler。

小问题:

倘若在进程解除对某种信号的阻塞之前这种信号产生过多次,将会如何处理?

解析:Linux下的实现方式:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。

* 小知识点:普通信号允许丢失、实时信号是不允许的

信号集(sigset_t)
因为在上图中,阻塞和未决标志都可以用相同的数据结构(位图)来表示,因此,阻塞和未决标志可以用相同的数据类型(sigset_t)来存储。
sigset_t称之为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态

信号集操作函数

#include <signal.h>
// 函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含任何有效信息
int sigemptyset(sigset_t  *set)
// 函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示该信号集的有效信息包含系统支持的所有信号
int  sigfillset(sigset_t  *set)
int  sigaddset(sigset_t  *set, int  signo)
int  sigdelset(sigset_t  *set,     int signo)
int  sigismember(const  sigset_t  *set,   int signo)

注意点:(1)在使用sigset_t类型的变量之前,一定要调用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。
(2)初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号

信号屏蔽字(sigprocmask):通过调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)

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

(1)若oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。
(2)若set是非空指针,则更改进程的信号屏蔽字,参数how至少如何更改
(3)若oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字

来看一下how参数的可选值

* SIG_BLOCK:set包含了我们希望添加到当前信号屏蔽字的信号,相当于mask=mask|set
* SIG_UNBLOCK:set包含了我们希望从当前信号屏蔽字中解除阻塞的信号,相当于mask=mask&~set
* SIG_SETMASK:设置当前信号屏蔽字为set所指向的值,相当于mask=set

如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达

#include <signal.h>
sigpending读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1

下面来写代码看看:

阻塞2号SIGINT信号,让其处于未决状态,去看看信号集数据的变化
代码如下(程序运行,每秒打印各信号的未决状态,让我们来观察一下现象):

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void diaplaysigset(sigset_t  *set)
{int i = 0;for (; i<32; i++){//判断指定信号是否在目标集合中if (sigismember(set, i)) {putchar('1');}else{putchar('0');}}puts("");
}
int main()
{// 定义信号集对象,并清空初始化sigset_t set, oset; sigemptyset(&set);// SIGINT:2号信号,相当有ctrl+Csigaddset(&set, SIGINT);// 设置阻塞信号集,阻塞SIGINT信号sigprocmask(SIG_BLOCK, &set, NULL);while (1){// 获取未决信号集sigpending(&oset);diaplaysigset(&oset);sleep(1);}return 0;
}

运行之:

由上图实现结果我们看到SIGINT信号被阻塞,所以按ctrl+C之后SIGINT信号处于未决状态,此时信号集数据由0表1。因为SIGQUIT信号未被阻塞,所以按ctrl+\终止程序。

Linux进程信号之阻塞信号相关推荐

  1. Linux 进程信号:信号的概念、生命周期、产生流程、阻塞

    信号的概念 信号的生命周期 信号的阻塞 信号的概念 信号 信号是一个软中断.操作系统通过信号通知某个进程发生了某件事件,然后中断这个进程当前操作,让它优先去处理这个事件. 我们在linux下常用的ki ...

  2. Linux 进程信号详细总结

    信号:信号是进程之间事件异步通知的一种方式,是一个软中断 作用:操作系统通过信号告诉进程发生了某个事件,打断进程当前的操作,去处理这个事件 信号在我们生活中无处不在,例如交通上的红绿灯,学校上下课的铃 ...

  3. Linux信号:SIGCHLD信号和僵尸进程

    1. SIGCHLD信号产生条件: (1)子进程终止: (2)子进程收到SIGSTOP信号被暂停: (3)子进程处于暂停状态,收到SIGCONT信号被唤醒. 2. 捕捉SIGCHLD,避免僵尸进程: ...

  4. 【B站视频笔记】linux 进程间通信(ipc)信号(软中断信号)signal库函数、可靠信号和不可靠信号、信号集sigprocmask(信号掩码、信号递达Delivery、信号未决Pending)

    [视频教程]Linux信号详解(可靠信号.不可靠信号.阻塞信号.信号处理函数) [博文]Linux信号 文章目录 背景 课程笔记 一.如何让程序在后台运行 1.加"&"符号 ...

  5. 信号 信号的注册 信号的发送 信号的阻塞

    目录 信号 信号的阻塞 信号的注册 信号的发送 信号   信号是信息的载体,怎么理解呢?就类似于烽火戏诸侯的周幽王点燃了烽火台发出了这个信号,然后各路诸侯收到了这个信号就过来救驾勤王了.   进程也是 ...

  6. 深入理解Linux进程间通信(IPC)-- 信号signal

    2. 信号(上) 2.1. 信号及信号来源 2.1.1 信号本质 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进程不 ...

  7. 可靠信号与不可靠信号

    来自:http://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html 一.信号及信号来源 信号本质 信号是软件中断,是在软件层次上 ...

  8. 深刻理解 Linux 进程间七大通信(IPC)

    前言 网络编程是 Linux C/C++的面试重点,今天我就来聊一聊进程间通信的问题,文章末尾列出了参考资料,希望帮助到大家. 篇幅有点长,希望大家耐心阅读. Linux 下的进程通信手段基本上是从 ...

  9. Linux系统编程31:进程信号之什么是信号的阻塞及相关术语(递达,未决,pending位图,handler位图)

    文章目录 (1)信号相关术语 (2)信号在内核中的表示 前面说过,操作系统发出信号之后,对于进程有可能不是立马就处理的,所以如果不是立即处理,那么在这个空档期间进程究竟对信号做了怎样的处理呢? (1) ...

最新文章

  1. Java多线程的11种创建方式以及纠正网上流传很久的一个谬误
  2. 5.2.4.最简单的模块源码分析3
  3. 使用纯粹的ABAP位操作实现两个整数相加
  4. 机器学习知识总结系列-机器学习中的优化算法总结(1-4)
  5. Leetcode--279. 完全平方数
  6. java基础 --- Arrays.asList():返回指定数组支持的固定大小列表
  7. Visio图形自动编号
  8. 解决android webkit的css postion:fixed支持问题
  9. bilibili怎么用用户名登录_b站(bilibili)账号只记得用户名忘了密码怎么办?实名认证能找回吗...
  10. Android FrameLayout 帧布局
  11. CSS3:伪类前的冒号和两个冒号区别
  12. 优必选悟空智能机器人怎么读绘本_优必选发布悟空机器人及操作系统ROSA,关于估值这么回应…...
  13. 手把手叫你用凤凰死刷手机(dead phone USB flashing)
  14. 教你利用铁威马NAS为电脑存储空间扩容
  15. 荔枝派zero编译rtl8723bs驱动并连接WiFi
  16. 大话functional编程语言
  17. 小波变换matlab代码,matlab小波变换代码
  18. python 比对匹配_用Python从头实现Needleman-Wunsch序列比对算法
  19. mac charles代理设置
  20. oracle wallet相关的bug|oracle wallet使用注意事项|ORA-28374: typed master key not found in wa

热门文章

  1. jmeter参数化设置
  2. 德声科技代理M-Live音视频播放器
  3. AOP中的切点、切面、通知等
  4. 大气校正6S与FLAASH计算与对比
  5. 爬虫攻守道 - 2023最新 - JS逆向 - Python Scrapy实现 - 爬取某天气网站历史数据
  6. Base64编码的原理及实现(源码)
  7. AWS Academy 学习平台建立 Learner Lab - 教师
  8. 汽车功能安全(一)~笔记
  9. 离线安装MySQL缺少libaio.so.1文件——并离线安装libaio.so.1
  10. nginx - nginx的安装部署