当前位置: 首页 > news >正文

进程间通信5:信号

引入

我们之前学习了信号量,信号量和信号可不是一个东西,不能混淆。

信号是什么以及一些基础概念

信号是一种让进程给其他进程发送异步消息的方式

  1. 信号是随时产生的,无法预测
  2. 信号可以临时保存下来,之后再处理
  3. 信号是异步发送的。因为这两个进程(发送信号的进程和接收信号的进程)互不相干

kill -l :查看信号

我们可以使用kill -l查看所有信号

他的输出大概是这样子

1) SIGHUP      2) SIGINT      3) SIGQUIT     4) SIGILL
5) SIGTRAP     6) SIGABRT     7) SIGBUS      8) SIGFPE
...
  1. 可以发现没有0、32、33号信号。1-31分别对应一个bit位
  2. 34到64号信号是实时信号:当开始执行实时信号,必须执行完才能执行其他的信号

信号处理

面对信号,我们有多种处理方式:

  1. 默认动作

  2. 自定义处理–>捕捉

  3. 忽略信号

我们就是通过signal系统调用来更改处理信号的方式

信号的产生

有三种方式:kill命令、键盘输入、系统调用

kill命令

使用kill命令

kill -num pid

常见的就是

kill -9 pid
#终止进程

键盘输入

像是输入ctrl c也可以停止当前进程

使用系统调用函数

  1. 使用kill函数:给指定的进程发送指定的信号
#include <sys/types.h>
#include <signal.h>int kill(pid_t pid, int sig);

成功返回0,失败返回-1,并设置errno

  1. raise函数:对调用raise的进程发送信号
#include <signal.h>int raise(int sig);

这个函数功能相当于调用

kill(getpid(), sig);
  1. abort函数
    调用该函数的进程直接退出

  2. 使用signal:修改信号

使用typedef简化写法:

typedef void (*signal_handler_t)(int);
signal_handler_t signal(int sig, signal_handler_t func);
//func是回调函数
//底层调用func的时候,func的参数就是sig

我们先传入要对哪个信号进行修改,再传入我们自定义的修改方法(func)
并且修改一次后一直生效

SIG_IGN
是ignore,忽略信号的意思,

signal(num, SIG_IGN)
//接收num信号后,不执行任何操作
//9号19号信号无法被忽略(可以区了解一下这两个信号的作用就能理解为什么了

异常

最常见的就是代码出现问题,爆出了异常

比如出现num/0的情况,产生SIGFPE信号,
访问野指针,产生11号信号SIGSEGV

Core Dump

  1. 是什么
    当一个进程要异常终止时,可以选择**把进程的用户空间内存数据全部保存到磁盘上,文件名通常是core,**这叫做Core Dump。

  2. 为什么
    进程异常终止通常是因为有Bug,比如非法内存访问导致段错误,事后可以用调试器检查core文件以查清错误原因,这叫做Post-mortem Debug(事后调试)。一个进程允许产生多大的core文件取决于进程的Resource Limit(这个信息保存 在PCB中)。默认是不允许产生core文件的, 因为core文件中可能包含用户密码等敏感信息,不安全,以及防止频繁崩溃导致生成大量core dump文件
    在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件。 首先用ulimit命令改变Shell进程的Resource Limit,允许core文件最大为1024K:

ulimit -c 1024

信号保存

信号其他相关常见概念

  1. 实际执行信号的处理动作称为信号递达(Delivery) (默认、忽略、自定义)
  2. 信号从产生到递达之间的状态,称为信号未决(Pending)(信号被临时保存)
  3. 进程可以选择阻塞 (Block )某个信号。(即无法执行该信号,具体原理是位图)
  4. 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作.
  5. 注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作
  6. 9和19号进程无法屏蔽

内核中的结构:三张表(重要)

在这里插入图片描述这张图显示了block位图记录信号是否阻塞、pending位图表示未决、handler表示函数指针数组,记录信号执行方法

对三张表的操作

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

基本接口(了解即可

#include <signal.h>// 初始化信号集为空(不包含任何信号)。
// 参数:
//   set - 指向要初始化的信号集。
// 返回值:
//   成功返回 0,失败返回 -1。
int sigemptyset(sigset_t *set);// 将信号集中的所有信号置为有效(包含所有信号)。
// 参数:
//   set - 指向要填充的信号集。
// 返回值:
//   成功返回 0,失败返回 -1。
int sigfillset(sigset_t *set);// 向信号集中添加一个指定的信号。
// 参数:
//   set   - 指向信号集。
//   signo - 要添加的信号编号。
// 返回值:
//   成功返回 0,失败返回 -1。
int sigaddset(sigset_t *set, int signo);// 从信号集中删除一个指定的信号。
// 参数:
//   set   - 指向信号集。
//   signo - 要删除的信号编号。
// 返回值:
//   成功返回 0,失败返回 -1。
int sigdelset(sigset_t *set, int signo);// 检查某个信号是否在信号集中。
// 参数:
//   set   - 指向信号集。
//   signo - 要检查的信号编号。
// 返回值:
//   如果信号在信号集中,返回 1;否则返回 0;失败返回 -1。
int sigismember(const sigset_t *set, int signo);

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

注意: 上面的接口都没有写入内核中,需要

sigprocmask:修改block位图

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

在这里插入图片描述

sigpending:查看未决信号集

#include <signal.h>int sigpending(sigset_t *set);

可以用于 查看哪些信号被屏蔽且处于等待状态。

补充
pending位图先清零,对应信号再递达

信号的处理

什么时候处理

进程从内核态切换到用户态时,OS检测并处理信号

如何处理

可以先看一下下面这个图
在这里插入图片描述

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

调用与屏蔽

当某个信号的处理函数被调用时,**内核自动将该信号加入进程的信号屏蔽字,**即处理期间,不允许再次调用。
当信号处理函数返回时自动恢复原来的信号屏蔽字,这样就保证了在处理某个信号时,如果这种信号再次产生,那么 它会被阻塞到当前处理结束为止。

结语

进程间通信到这里就暂时结束了(虽然内存池还差代码实现、共享内存还完全没写,但我准备之后用到了再写),希望对大家有帮助

相关文章:

进程间通信5:信号

引入 我们之前学习了信号量&#xff0c;信号量和信号可不是一个东西&#xff0c;不能混淆。 信号是什么以及一些基础概念 信号是一种让进程给其他进程发送异步消息的方式 信号是随时产生的&#xff0c;无法预测信号可以临时保存下来&#xff0c;之后再处理信号是异步发送的…...

性能测试及调优

一、性能测试介绍 1、什么叫做性能测试&#xff1f; &#xff08;1&#xff09;通过某些工具或手段来检测软件的某些指标是否达到了要求&#xff0c;这就是性能测试 &#xff08;2&#xff09;指通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指…...

实战基于LangChain和ChatGLM私有化部署聊天机器人

本文主要阐述了如何使用第二代6B模型进行对话训练&#xff0c;以及如何通过微调来提高大模型的性能。文中提到了在8501端口上启动第二代6B模型&#xff0c;并使用极简模板进行请求。与第一代模型相比&#xff0c;第二代6B模型具有更强的对话能力&#xff0c;并且可以通过微调来…...

利用adb工具安装卸载安卓平板(手机)软件

参考链接&#xff1a; 1、ADB 操作命令详解及用法大全 2、全面掌握Android调试工具箱&#xff1a;ADB与实用程序实战 平时使用小米手机没有感觉&#xff0c;miui系统做的确实好。最近买了个水货学习系统平板&#xff08;主要看重硬件配置&#xff0c;性价比很高&#xff0c;但…...

基于docker进行任意项目灵活发布

引言 不管是java还是python程序等&#xff0c;使用docker发布的优势有以下几点&#xff1a; 易于维护。直接docker命令进行管理&#xff0c;如docker stop、docker start等&#xff0c;快速方便无需各种进程查询关闭。环境隔离。项目代码任何依赖或设置都可以基本独立&#x…...

Datatables:监听行内文本框,进行行内数据修改;计算行总和

一、监听行内文本框&#xff0c;进行行内数据修改 效果 修改数量、单价会自动计算金额&#xff08;金额数量*单价&#xff09; 实现 1、增加行的class 2、数据监听、修改数值 "initComplete": function() {// 监听数量和单价输入框的变化$(document).on(input, .…...

对于某些原型或UI软件的个人看法(2024/11)

由于我这几天&#xff0c;一边敲代码&#xff0c;一边进行页面布局设计与编码&#xff0c;发现可能就一个卡片&#xff0c;我都得调很久样式&#xff0c;觉得这样改很累也没效率&#xff0c;页面也不是很美观。所以我想到了ui设计&#xff0c;我可以先进行ui设计&#xff0c;然…...

嵌入式硬件实战提升篇(二)PCB高速板设计 FPGA核心板带DDR3 PCB设计DDR全面解析

引言&#xff1a;设计一款高速板&#xff0c;供读者学习&#xff0c;FPGA核心板&#xff0c;带一颗DDR3内存&#xff0c;FPGA型号&#xff1a;XC6SLX16-2FTG256C。 随着嵌入式硬件技术的快速发展&#xff0c;高速板设计逐渐成为嵌入式系统设计中的核心技术之一。高速板的设计要…...

亚信安全携手飞书“走近先进” 与保隆科技探索制造业数字化转型

亚信安全携手飞书组织举办“走近先进”活动。近日活动“走近”了中国汽车供应链百强、上海市制造业五十强企业——上海保隆汽车科技股份有限公司&#xff08;以下简称“保隆科技”&#xff09;。活动围绕“突破桎梏 加速升级”的主题&#xff0c;聚焦企业数字化转型的核心议题&…...

【C++篇】排队的艺术:用生活场景讲解优先级队列的实现

文章目录 须知 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助吗&#xff1…...

VTK的基本概念(一)

文章目录 三维场景的基本要素1.灯光2.相机3.颜色4.纹理映射 三维场景的基本要素 1.灯光 在三维渲染场景中&#xff0c;可以有多个灯光的存在&#xff0c;灯光和相机是三维渲染场景的必备要素&#xff0c;如果没有指定的话&#xff0c;vtkRenderer会自动创建默认的灯光和相机。…...

error LNK2001: 无法解析的外部符号 memcpy strcmp strlen

0>LIBMY_static.lib(pixdesc.obj) : error LNK2001: 无法解析的外部符号 __imp_abort 10>LIBMY_static.lib(random_seed.obj) : error LNK2001: 无法解析的外部符号 __imp_abort 10>postprocess.obj : error LNK2001: 无法解析的外部符号 __imp_abort 10>LIBMY_sta…...

打造智能扩容新纪元:Kubernetes Custom Metrics深度解析

自定义指标:Kubernetes Auto Scaling的革命 1. 引言 1.1 Kubernetes与Auto Scaling Kubernetes作为当今容器编排的事实标准,提供了强大的自动化能力,其中Auto Scaling(自动扩缩容)是其核心特性之一。Auto Scaling允许Kubernetes集群根据当前负载动态调整资源,以应对不…...

【K8s】专题十五(4):Kubernetes 网络之 Calico 插件安装、切换网络模式、卸载

本文内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01; 如果对您有帮助&#xff0c;烦请点赞、关注、转发、订阅专栏&#xff01; 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】&#xff08;全…...

Unity类银河战士恶魔城学习总结(P141 Finalising ToolTip优化UI显示)

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址&#xff1a;https://www.udemy.com/course/2d-rpg-alexdev/ UI部分暂时完结&#xff01;&#xff01;&#xff01; 本章节优化了UI中物品描述的显示效果&#xff0c;技能描述的显示效果 并且可以批…...

c++(入门)

1. 引用 引用的定义 引用是另一个变量的别名&#xff0c;它在声明时必须被初始化&#xff0c;并且一旦初始化后&#xff0c;它就始终引用那个变量。 引用的语法 引用的声明方式是在变量名前加上&符号。 引用的特点 引用必须在声明时初始化。引用一旦初始化后&#x…...

【优选算法】前缀和

目录 一、[【模板】前缀和](https://www.nowcoder.com/practice/acead2f4c28c401889915da98ecdc6bf?tpId230&tqId2021480&ru/exam/oj&qru/ta/dynamic-programming/question-ranking&sourceUrl%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595…...

Spring Bean 的生命周期详解

所谓万物皆对象&#xff0c;对于一个 bean 而言&#xff0c;从出生到死亡&#xff0c;他要经历哪些阶段呢&#xff1f; 生命周期 理解对象的生命周期&#xff0c;可以帮助我们更好的做一些扩展。 一个对象从被创建到被垃圾回收&#xff0c;可以大致分为这 5 个阶段&#xff1a…...

MySQL【知识改变命运】12

视图 1&#xff1a;什么是视图2&#xff1a;创建视图使用视图&#xff08;视图的好处&#xff09;2.1.隐藏敏感字段2.2.对外提供统一访问3&#xff1a;视图和真实表进⾏表连接查询 4&#xff1a;修改视图数据4.1&#xff1a;通过真实表修改数据&#xff0c;会影响视图4.2&#…...

shell编程(完整版)

目录 一、shell脚本解释器 二、shell脚本的执行 三、变量的使用 四、永久环境变量 按用户设置永久环境变量 文件路径&#xff1a; 示例步骤&#xff1a; 删除永久环境变量 五、脚本程序传递参数怎么实现 六、用编程进行数学运算 shell中利用expr进行运算 运算与变量…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...