首页 > 系统相关 >【Linux】信号(二)

【Linux】信号(二)

时间:2024-06-08 13:59:04浏览次数:24  
标签:0000 sigset 递达 阻塞 信号 Linux pending

上一章节我们进行了信号产生的讲解。
在这里插入图片描述
本节将围绕信号保存展开,并会将处理部分开一个头。

目录

信号保存:

信号的一些概念:

  • 实际执行信号的处理动作称为信号递达(Delivery)
  • 信号从产生到递达之间的状态,称为信号未决(Pending)。
  • 进程可以选择阻塞 (Block )某个信号。

对于递达:也就是我们之前一直在说的处理,仍然是3种处理方法

  1. 默认行为 2. 忽略行为 3. 自定义行为

对于未决:是信号产生到递达之间的状态。

对于阻塞:当我们阻塞一个信号,信号一旦产生,永不递达,知道解除阻塞状态。

那么现在我们要进行一个概念的区分。
一个信号如果阻塞和他是否未决有关系吗?
这就像你讨厌一个老师(阻塞),你不会做他布置的作业(递达),但是并不妨碍你将作业记下来(未决)。所以其实是没关系的!

但以上都只是概念
我们要继续深入原理:
我们之前说过发信号实际就是在task_struct中进行pending位图的修改,但除了pending我们还有一个block位图与一张hanler表。

block对应阻塞,pending对应未决,handler对应递达。
在这里插入图片描述


既然我们最熟悉pending,那么就先从pending开始。
我们说过pending是一张位图。

0000 0000 0000 0000 0000 0000 0000 0000
第0个比特位不用,比特位的位置代表信号编号。
比特位的内容代表信号是否收到。


再来看handler表。
提到handler表我们又要把signal函数拿出来在这里插入图片描述
handler表的每个元素实际就是在这里插入图片描述
这个类型的函数指针。
我们使用signal时,实际上就是在修改handler表,将信号编号直接对应到这个数组的下标

在这里插入图片描述


最后来看block位图。
和pending是非常类似的。

0000 0000 0000 0000 0000 0000 0000 0000

比特位的位置:代表信号编号
比特位的内容:当前信号是否阻塞


所以只要有两个位图+一张表 就能让进程识别信号。

最后在补充两个概念。

  • 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作.
  • 阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

关于信号保存的接口:

在说到接口前我们还需要铺垫一个linux提供的一个类型sigset_t。

sigset_t的解释:

从上图来看,每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。
因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。
等了解了sigset_t将详细介绍信号集的各种操作。 阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该理解为阻塞而不是忽略。

linux中定义为下:
在这里插入图片描述
我们先自己模拟一个位图便于理解sigset_t。
在这里插入图片描述
同样,我们不推荐自己操作位图,因为不同系统位图的结构可能不同,就不能正确的运行,因此,OS也提供了一批函数进行操作这个类型。

对应的操作接口:

#include <signal.h>
int sigemptyset(sigset_t *set);
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);

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

函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示 该信号集的有效信号包括系统支持的所有信号。

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

这四个函数都是成功返回0,出错返回-1。sigismember是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种 信号,若包含则返回1,不包含则返回0,出错返回-1.

我们现在知道了信号位图和对应的操作,那么怎么获得block与pending??

因为task_struct是属于内核的,所以只有OS可以进行获取与修改,所以OS就要提供对应的系统调用供我们使用。


我们先来看block的操作函数

sigprocmask:

在这里插入图片描述

参数解释:

如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则 更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号 屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值。

在这里插入图片描述

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

sigpending:

我们对于pending位图该怎么操作呢?
实际上我们已经学完了!就是信号发送的5种方式,修改了对应的位图,那么怎么进行获取?
在这里插入图片描述
使用上图函数即可获取。

代码实践:

阶段一:


我们先将获取pending,随后对2号屏蔽,观察现象。
在这里插入图片描述

进行kill -2
在这里插入图片描述
现象:
在这里插入图片描述


阶段二:
此时我们再尝试恢复一下对二号信号。
但要捕捉一下,否则解除屏蔽的瞬间就直接进行终止了。

改动后的代码:
在这里插入图片描述

现象:
在这里插入图片描述
持续更新…

标签:0000,sigset,递达,阻塞,信号,Linux,pending
From: https://blog.csdn.net/2301_78636079/article/details/139542592

相关文章

  • SELinux 基本原理
    首发公号:Rand_csSELinux基本原理本文讲述SELinux保护安全的基本原理安全检查顺序不废话,直接先来看张图当我们执行系统调用的时候,会首先对某些错误情况进行检查,如果失败通常会得到一些error信息,通过查看全局变量errno可以知道到底是哪一类错误随后进行DAC检查,简......
  • PyQT5信号与槽的连接
    方法一:fromPyQt5.QtCoreimport*fromPyQt5.QtWidgetsimport*importsysclassAutoSignalSlot(QWidget):def__init__(self):super().__init__()self.setWindowTitle("信号与槽自动连接")self.resize(300,100)self.okB......
  • Linux学习总结
    Linux笔记Linux目录结构1./bin目录/bin目录包含了引导启动所需的命令或普通用户可能用的命令(可能在引导启动后)。这些命令都是二进制文件的可执行程序(bin是binary--二进制的简称),多是系统中重要的系统文件。2./sbin目录/sbin目录类似/bin,也用于存储二进制文件。因......
  • Linux:权限
    文章目录shell命令以及运行原理Linux下用户的分类Linux权限管理文件权限值的表示方法字符表示方法8进制数值表示方法权限的修改权限掩码目录文件的权限关于权限的总结关于权限的总结shell命令以及运行原理Linux严格意义上说的是一个操作系统,我们称之为“核心(kernel)......
  • Linux 中date命令
     date主要用于显示日期,若是不以加号作为开头,则表示要设定时间,而时间格式为MMDDhhmm[[CC]YY][.ss],其中MM为月份,DD为日,hh为小时,mm为分钟,CC为年份前两位数字,YY为年份后两位数字,ss为秒数。001、最基本的用法[root@PC1test2]#date##输出日期SatJun812:......
  • PyQT5信号刷新时间
    importtimefromPyQt5.QtCoreimport*fromPyQt5.QtWidgetsimport*importsysclassBackendThread(QThread):update_date=pyqtSignal(str)defrun(self):whileTrue:data=QDateTime.currentDateTime()currentTim......
  • PyQT5之信号关闭窗口
    fromPyQt5.QtCoreimport*fromPyQt5.QtWidgetsimport*importsysclassWinSignal(QWidget):#定义一个信号button_clicked_signal=pyqtSignal()def__init__(self):super().__init__()self.setWindowTitle("为窗口类添加信号")......
  • 嵌入式Linux系统编程 — 1.5 文件描述符详解
    目录1文件描述符简介1.1文件描述符特点1.2标准文件描述符1.3文件描述符的生命周期2 fcntl()函数2.1fcntl()函数简介2.2复制文件描述符(F_DUPFD)2.3获取/设置文件状态标志(F_GETFL/F_SETFL)1文件描述符简介文件描述符(FileDescriptor)是Linux和UNIX系统编......
  • 信号与槽N对N
    ···fromPyQt5.QtCoreimport*classNNSignal(QObject):#定义一个信号signal1=pyqtSignal()#发送3个参数的信号signal2=pyqtSignal(int)signal3=pyqtSignal()def__init__(self):super().__init__()self.signal1.connect(self.signal_call1)s......
  • Linux(Windows)网络配置(超详细)
    Linux网络配置三种模式(以下是理论,不想看可直接跳过):        桥接模式(bridged):也就是将虚拟机的虚拟网络适配器与主机的物理网络适配器进行交接,虚拟机中的虚拟网络适配器可通过主机中的物理网络适配器直接访问到外部网络。简而言之,这就好像在局域网中添加了一台新的、......