Linux的学习之路:20、进程信号(2)

news2024/12/23 18:34:06

摘要

本章讲一下进程信号的阻塞信号和捕捉信号和可重入函数

目录

摘要

一、阻塞信号

1、阻塞信号

2、信号集操作函数

二、捕捉信号

1、内核如何实现信号的捕捉

2、代码实演

三、可重入函数


一、阻塞信号

1、阻塞信号

 实际执行信号的处理动作称为信号递达(Delivery)
信号从产生到递达之间的状态,称为信号未决(Pending)。
进程可以选择阻塞 (Block )某个信号。
被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动。
注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。
忽略是已经处理了,但是我不搭理你,但是阻塞就是不会被送达,就特别像堵车,只要的堵着就是收不到这个就是阻塞信号。

下面这个图就是信号在内核中显示的方式

每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。在上图的例子中,SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。

SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。

SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?POSIX.1允许系统递送该信号一次或多次。Linux是这样实现的:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。

从上图来看,每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态 ,所以总结一下就是每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。

2、信号集操作函数

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

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

注意,在使用sigset_ t类型的变量之前,一定要调 用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。

初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效号。

#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);

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

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

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

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

sigpending

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

二、捕捉信号

1、内核如何实现信号的捕捉

如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了SIGQUIT信号的处理函数sighandler。 当前正在执行main函数,这时发生中断或异常切换到内核态。 在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT递达。 内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函 数,sighandler和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是 两个独立的控制流程。 sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态。 如果没有新的信号要递达,这次再返回用户态就是恢复main函数的上下文继续执行了

2、代码实演

首先就是代码捕捉signal这个函数代码测试如下,如下图,我把所有的信号都捕捉了,那么还能杀掉这个进程吗,是不是都捕捉了就杀不掉进程了?

#include <iostream>
#include <string>
#include <unistd.h>
#include <signal.h>
using namespace std;

void catchSig(int signum)
{
    cout << "获取一个信号:" << signum << endl;
}

int main()
{
    cout << "我的pid: " << getpid() << endl;
    for (int sig = 1; sig <= 31; sig++)
        signal(sig, catchSig);
    while (true)
        sleep(1);
    return 0;
}

 

当然不是这个可以用9号信号给杀掉,如下图,因为操作系统肯定是想到了,所以这里就设置了几个信号进行杀掉进程。

 

这边写了一个函数重复捕捉信号,另外写一个bash程序,一直发送kill信号如下,到9号信号就会被杀掉这样就得出了还是有可以解决的。

 

三、可重入函数

main函数调用insert函数向一个链表head中插入节点node1,插入操作分为两步,刚做完第一步的 时候,因为硬件中断使进程切换到内核,再次回用户态之前检查到有信号待处理,于是切换 到sighandler函数,sighandler也调用insert函数向同一个链表head中插入节点node2,插入操作的 两步都做完之后从sighandler返回内核态,再次回到用户态就从main函数调用的insert函数中继续 往下执行,先前做第一步之后被打断,现在继续做完第二步。结果是,main函数和sighandler先后 向链表中插入两个节点,而最后只有一个节点真正插入链表中了。

像上例这样,insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入,insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为 不可重入函数,反之,如果一个函数只访问自己的局部变量或参数,则称为可重入(Reentrant) 函数。

总结一下就是一个大无穷然后内核态在这个横线下面,然后沿着这个大无穷进行来回切换访问。

如果一个函数符合以下条件之一则是不可重入的:
调用了malloc或free,因为malloc也是用全局链表来管理堆的。
调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1622313.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

文末送资料 | AI大模型接入指南:免费畅聊公众号新时代!附搭建教程

目录 今天内容有点意思&#xff01; 福利&#xff1a;拉到最后&#xff0c;免费送资料&#xff0c;你想要的全都有 我把公号接入了&#xff0c;字节跳动的云雀AI大模型&#xff01; 先给大家看几个案例 重点来了 如何将公号接入AI大模型呢&#xff1f; 1、创建AI聊天机器…

海南封关怎么看?win战略会任志雄解析

今年海南自由贸易港建设也进入了新阶段:将在2025年年底前适时启动全岛封关运作,封关后的海南将以全新姿态迎接更广泛的发展机遇。 封关在即,企业有何感受?还有哪些准备工作?封关后的海南将呈现怎样的状态?近日,红星资本局记者深入实地了解海南自贸港如何成型起势。 利好当…

快手不发作品ip地址会变吗

在数字时代&#xff0c;我们每个人的在线行为都留下了独特的痕迹。这些痕迹不仅仅是我们的言论或行为&#xff0c;还包括我们的IP地址——一个在网络世界中标识我们位置的数字标签。近年来&#xff0c;随着短视频平台的兴起&#xff0c;如快手这样的应用已经深入人们的日常生活…

sentinel-1.8.7与nacos-2.3.0实现动态规则配置、双向同步

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; sentinel-1.8.7与nacos-2.3.0实现动态规则配置、双向同步 ⏱️ 创作时…

2024年大数据应用、智能控制与软件工程国际会议(BDAICSE2024)

2024年大数据应用、智能控制与软件工程国际会议(BDAICSE2024) 会议简介 我们诚挚邀请您参加2024年大数据应用、智能控制和软件工程国际会议&#xff08;BDAICSE2024&#xff09;。这次会议将在美丽的长沙市举行。 本次大会旨在汇聚全球大数据应用、智能控制、软件工程等领…

常见大厂面试题(SQL)02

小鹏面试题: 小鹏汽车充电每辆车连续快充最大次数 原表charging_data idcharge_timecharge_typeXP10012023/11/20 8:45快充XP10012023/11/21 20:45快充XP10012023/11/22 8:45快充XP10012023/11/23 8:45慢充XP10012023/11/25 8:45快充XP10022023/11/25 8:45快充XP10022023/11/…

kubernetes中Pod资源的使用限制

一、概述 当kubernetes调度创建Pod后&#xff0c;Pod是否有足够的资源来运行容器&#xff0c;是非常重要的。资源分为两种类型——容器请求的资源和容器被限制的资源。 请求和限制是kubernetes控制集群cpu和内存等资源的重要方式&#xff0c;他们是两种不同的机制 容器请求的资…

C语言之回调函数+可变参数__VA_ARGS__:用法实例(四十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

GaussDB数据库SQL系列-聚合函数

背景 在这篇文章中&#xff0c;我们将深入探讨GaussDB数据库中聚合函数的使用和优化。聚合函数是数据库查询中非常重要的工具&#xff0c;它们可以对一组值执行计算并返回单个值。例如&#xff0c;聚合函数可以用来计算平均值、总和、最大值和最小值。 这些功能在数据分析和报…

C语言 | Leetcode C语言题解之第48题旋转图像

题目&#xff1a; 题解&#xff1a; void swap(int* a, int* b) {int t *a;*a *b, *b t; }void rotate(int** matrix, int matrixSize, int* matrixColSize) {// 水平翻转for (int i 0; i < matrixSize / 2; i) {for (int j 0; j < matrixSize; j) {swap(&matr…

Linux_网络基础2_3

文章目录 一、应用层协议1.我写的socket是在干什么&#xff1f;2.再谈"协议"1.问题1 # 2.问题23.造轮子——定制应用协议4.使用json来完成应用协议1.安装库2.使用 —— 序列化3.使用 —— 反序列化 二、HTTP协议1.认识URL2.http协议的请求格式和响应格式3.编写响应 -…

大模型(e.g., ChatGPT)里面的一些技术和发展方向

文章目录 如何炼成ChatGPT如何调教ChatGPT如何武装ChatGPT一些大模型的其他方向prompt tuningInstruction tuning 这个是基于视频 https://www.bilibili.com/video/BV17t4218761&#xff0c;可以了解一下大模型里面的一些技术和最近的发展&#xff0c;基本都是2022你那以来的发…

Spring Boot整合Redisson的两种方式

项目场景 Spring Boot整合Redisson的两种方式&#xff0c;方式一直接使用yml配置&#xff0c;方式二创建RedissonConfig配置类。 前言 redisson和redis区别&#xff1a; Redis是一个开源的内存数据库&#xff0c;支持多种数据类型&#xff0c;如字符串、哈希、列表、集合和有序…

tailwindcss在使用cdn引入静态html的时候,vscode默认不会提示问题

1.首先确保vscode下载tailwind插件&#xff1a;Tailwind CSS IntelliSense 2.需要在根目录文件夹创建一个tailwind.config.js文件 export default {theme: {extend: {// 可根据需要自行配置&#xff0c;空配置项可以正常使用},}, }3.在html文件的标签中引入配置文件&#xf…

基础环境:wsl2安装Ubuntu22.04 + miniconda

服务器相关信息&#xff1a; Thinkpad p1 gen5 64G 2T 3080ti&#xff0c;自带的有nvidia-smi显卡驱动。使用wsl2安装Ubuntu22.04 miniconda目标&#xff1a;安装gpu版本的PyTorch2.1.2&#xff08;torch2.1.2/cu117 torchvision0.16.2/cu117&#xff09; 处理器 12th Gen I…

ADS8866 ADC转换芯片驱动调试

目录 ADS8866 ADC转换芯片驱动调试 开发环境&#xff1a; ADS8866功能简介 硬件连接 SPI3的软件驱动 ADS8866通讯时序分析 ADS8866驱动 ADS8866 ADC转换芯片驱动调试 开发环境&#xff1a; 主控芯片&#xff1a;STM32F103RCT6、ADS8866转换芯片、使用HAL库进行开发。 …

Chitosan-Rhodamine B 罗丹明B标记壳聚糖

Chitosan-Rhodamine B 罗丹明B标记壳聚糖 【中文名称】罗丹明B标记壳聚糖 【英文名称】Chitosan-RB 【结 构】 【品 牌】碳水科技&#xff08;Tanshtech&#xff09; 【纯 度】95%以上 【保 存】-20℃ 【规 格】50mg,100mg,500mg,1g,5g,10g 【产品特性】 Rh…

libVLC 专栏介绍

本专栏主要界面libVLC的使用&#xff0c;详细介绍了相关用法&#xff0c;使用Qt作为显示界面&#xff0c;不仅可以了解Qt的使用&#xff0c;QSS的美化&#xff0c;更能够熟悉libVLC核心接口的使用&#xff0c;最后打造一款属于自己的精美播放器。 每一节都有单独的源码供查看。…

企业微信hook接口协议,ipad协议http,发送小程序

发送小程序 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信send_userid是long要发送的人或群idisRoom是bool是否是群消息 请求示例 {"uuid":"543ed7f3-6ec1-4db8339a140f7","send_userid":788130255…

gps路径压缩算法

公司的gps点位特别多,导致数据存储以及查询都会造成一定的压力. 所以我们需要使用gps路径压缩算法 我调研了两种: k-means 和 Douglas-Peucker k-means 压缩的底层原理是: 自定义簇的数量,假设是100个,那么就会计算所有gps点,把最相近的点,放在一个簇里,以此类推,计算出100个…