Linux——进程信号3

news2025/4/23 9:52:33

内核如何实现信号的捕捉

信号捕捉的方法出了我们之前的signal之外,还有其它方法

sigaction

sigaction:检查或更改一个信号的动作即捕捉信号

第一个参数,要捕捉的信号对应的编号,第二个参数:结构体(这个结构体类型名和函数名一样,这里不是回调这个函数),该类型是输入型参数,第三个参数 输出型参数,对于这个信号的老的处理方法,类似于sigprocmask。成功返回0,失败返回-1,并设置错误码

sigaction结构体

第一个是信号捕捉对应的回调函数,第2,4,5个参数暂时不考虑

基本用法

makefile里面最后这个-fpermissive是防止打印默认处理方法时,在强制转换那里出错,加上之后就不会报错,但是会变成警告

我们把二号信号的处理方法设置为忽略

此时默认处理就是1,1是忽略

处理信号的时候,执行自定义动作,如果在处理信号期间又来了同样的信号,OS会如何处理?

本质:为什么要有block。

当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来的信号屏蔽字,这样就保证了在处理某个信号时,如果这种信号再次产生,那么 它会被阻塞到当前处理结束为止。 如果在调用信号处理函数时,除了当前信号被自动屏蔽之外,还希望自动屏蔽另外一些信号,则用sa_mask字段说明这些需要额外屏蔽的信号,当信号处理函数返回时自动恢复原来的信号屏蔽字。 sa_flags字段包含一些选项,本章的代码都把sa_flags设为0,sa_sigaction是实时信号的处理函数

验证:

我们在处理信号的时候sleep10秒

这10s期间,我们不断发送二号信号,我们此时看到我们发送的二号信号没有被处理

我们观察一下,上述过程发生期间,pending位图

我们把3-7号信号也加入

我们可以看出在我们处理2号信号期间,其它信号也是被block的,直到信号处理完毕,才会处理下一个信号。

可重入函数

信号捕捉并没有创建新的进程或者线程

当我们头插node1调用insert函数时,收到了二号信号,二号信号的捕捉方法里面也是一个头插,此时将node2进行头插,之后返回node1头插,这里俩次头插让head改变了俩次,最后造成了n2节点丢失,内存泄漏的问题。这种现象叫函数重入

这种因为时序产生的问题存在,而且不好被排查。

可重入函数:一个函数在特定的时间段内被多个执行流重复进入,这种情况就叫重入函数。而该函数重入后没有问题,称之为可重入函数。而上面的insert方法,出现了问题这种就叫不可重入函数。这俩种函数都是函数的一种特征,大多数函数都是不可重入的。

如果一个函数符合以下条件之一则是不可重入的:

调用了malloc或free,因为malloc也是用全局链表来管理堆的。

调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构。

volatile

捕捉二号信号后,让flag=1,我们看while循环此时能不能退出

我们发现此时while循环退出。

编译器有时候会自动的给我们进行代码优化。

gcc里面O3是优化级别最高的,我们添加该选项

优化后,我们执行程序,发送二号信号

此时flag改变后,while循环居然不退出。

这是因为之前编译器未优化。我们定义的flag是全局变量,在内存中给flag开辟空间后,我们执行代码让flag=1,代码是在CPU中执行的,flag的值读到CPU寄存器中进行修改,将修改后的值返回。

当优化之后,编译器发现main函数里没有任何一个语句是修改flag的,编译器在第一次启动时候,直接把flag的值0放到edx中,之后while循环做检测,CPU就自行检测flag,不再进行访问内存,当修改flag时,flag有0变1,但此时只是将内存中的flag修改了,CPU中的flag的值还是0

也就是说因为有优化的存在,数据被优化到了寄存器当中,进而导致程序不会访问内存,只访问寄存器的值,也就是说让CPU无法看到内存了,导致内存被遮盖。

为解决这种问题,即每次让CPU去访问内存,保证内存的可见性,引入了volatile关键字,加入之后由于有O3所以代码既被优化,有保证了内存的可见性。

上面把数据直接放入CPU寄存器的优化发生在编译的时候。

SIGCHLD信号

用wait和waitpid函数清理僵尸进程,父进程可以阻塞等待子进程结束,也可以非阻 塞地查询是否有子进程结束等待清理(也就是轮询的方式)。

采用第一种方式,父进程阻塞了就不 能处理自己的工作了;采用第二种方式,父进程在处理自己的工作的同时还要记得时不时地轮询一 下,程序实现复杂。

其实,子进程在终止时会通过操作系统给父进程发SIGCHLD(17号信号)信号(注:只有Linux下才有这种情况),该信号的默认处理动作是忽略,父进程可以自 定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程 终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。

当运行程序后,子进程退出时,我们发现我们说到了SIGCHLD信号,证明了子进程退出会给父进程发送信号。

若有多个子进程,多个子进程同时退出,我们设置一个循环用wait()去进行回收,但如果10个子进程里面前5个子进程要退出。我们用while循环检测到前五个退出了并回收,那对于第六个子进程我们需不需要检测并回收?

答案是需要检测因为waitpid和wait除了回收之外还可以检测子进程是否退出,当我们同一时间收到5个SIGCHLD信号,可SIGCHLD这个信号对应的比特位只有一个,所以实际我们只会收到一个信号,因为pending位图中只有一个比特位表示是否收到某一个信号。

当我们检测到第六个子进程没退出,这时信号处理只能被阻塞,此时main执行流的事情就没办法执行了,为了解决此问题,我们可采用while循环用vector非阻塞的去遍历所有进程,然后回收掉该回收的进程,即退出了就回收,没退出就下一个。

若不想用vector保存,我们可将waitpid第一个参数设置为-1,-1的效果等价于wait,相等于等待任意退出的进程。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void handler(int sig)
{
   pid_t id;
   while( (id = waitpid(-1, NULL, WNOHANG)) > 0){
   printf("wait child success: %d\n", id);
}
   printf("child is quit! %d\n", getpid());
}
int main()
{
 signal(SIGCHLD, handler);
 pid_t cid;
 if((cid = fork()) == 0)
  {//child
   printf("child : %d\n", getpid());
   sleep(3);
   exit(1);
  }
while(1)
   {
     printf("father proc is doing some thing!\n");
     sleep(1);
   }
return 0;
}

若我们不关心进程的退出码,退出信号等。我们又该如何处理。

答:如果我们不想等待子进程,并且我们还想让子进程退出之后自动释放僵尸子进程。我们可用SIG_IGN

while :; do ps ajx | head -1 &&ps axj | grep mysignal|grep -v grep ; sleep 1; echo "-----------------------------------"; done

我们看到5s后子进程退出状态变为Z

我们手动对子进程进行忽略

5S后我们未看到子进程

SIG_CHLD的处理动作默认就是忽略,可我们又显示的设置了一个忽略,我们也可以发现设置忽略和没设置忽略差别很大,因为这俩个忽略的概念不一样,OS级别的忽略是默认的动作,即什么也不做,该是僵尸就是僵尸,而我们自己的SIG_IGN是用户告诉了OS我们要真的忽略,即在子进程退出时,直接把子进程释放掉。

我们验证进程暂停

我们让子进程sleep(100),暂时不退出

我们暂停了19号信号,发送了暂停信号,我们看到父进程受到了子进程的SIGCHLD信号。

因此在进程等待的时候,我们一般把等待方式设置为非阻塞,因为有可能子进程会暂停,我们必须得进行检测,检测到退出,我们就进行回收。

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

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

相关文章

4种整流电路、5种滤波电路

目录 基本电路变压电路整流电路半波整流电路全波整流电路桥式整流电路倍压整流电路 滤波电路电容滤波电路电感滤波电路RC滤波电路LC滤波电路有源滤波电路 整流滤波电路总结常用整流电路性能对照常用无源滤波电路性能对照电容滤波电路输出电流大小与滤波电容量的关系常用整流滤波…

nodejs+vue大学招聘求职网站

该系统的基本功能包括学生注册登录&#xff0c;企业注册登录&#xff0c;发布个人简历&#xff0c;发布企业招聘信息&#xff0c;新闻资讯&#xff0c;招聘信息&#xff0c;企业管理&#xff0c;学生信息管理&#xff0c;招聘信息管理,修改密码等功能。 系统首页 后台界面 1.…

【设计模式】设计模式简述及类图

设计模式的分类依据两个准则&#xff0c;第一个是目的准则&#xff0c;即模式是用来完成什么工作的。模式依据其目的可以分为创建型、结构型和行为型三种。创建型模式和对象的创建有关&#xff0c;结构型模式处理类或对象的组合。行为型模式对类或对象怎样交互和怎样分配职责进…

随机变量X,分布函数X~F(x)的理解。

1.随机变量X 1.通常认知的"x"与随机变量X 我们通常意义上的 x 是自变量&#xff0c;y f(x) 中的自变量。 但是 X 更多意义是 对应法则 " f " &#xff0c;X完整写法是 X(ω) ω ∈ Ω。 X这个对应法则&#xff0c;可以将样本点映射到实数轴上。 那么X这…

初识linux之POSIX信号量

目录 一、信号量的概念 1. 信号量的作用 2. 信号量的PV操作 3. 信号量操作接口 3.1 初始化信号量 3.2 销毁信号量 3.3 等待信号量&#xff08;P操作&#xff09; 3.4 发布信号量&#xff08;V操作&#xff09; 二、循环队列 三、使用循环队列模拟实现生产消费模型 1…

Spring 组成及拓展

1. Spring 组成 1.1 Spring的七大模块 1.2拓展 在Spring官网有这个介绍&#xff1a;现代化的Java开发&#xff01;说白了就是基于Spring的开发 - SpringBoot - 一个快速开发的脚手架 - 基于SpringBoot可以快速的开发单个微服务。 - 约定大于配置&#xff01; - SpringC…

ENVI实现遥感图像的最小距离、最大似然、支持向量机分类

目录 1 分类需求 2 具体操作 2.1 ROI区域绘制 2.2 最小距离法 2.3 最大似然法 2.4 支持向量机 3 精度评定 4 分类后处理 4.1 小斑块处理 4.2 分类统计 4.3 修改类别颜色 5 结果对比 本文介绍基于ENVI软件&#xff0c;实现最小距离法、最大似然法与支持向量机三种遥…

达索的多领域系统级仿真软件Dymola 2023版本下载与安装配置教程

目录 前言一、Dymola 安装二、使用配置总结 前言 Dymola是由Dassault Systemes公司开发的一款基于物理建模的多领域系统级仿真软件。它包含了多个领域的建模和仿真工具&#xff0c;如机械、电气、液压、热力学、控制等&#xff0c;可以用于对各种系统进行建模和仿真&#xff0…

GcExcel for Java edition 6.1.0 Crack

高速 Java Excel 电子表格 API 库,在 Java 应用程序中以编程方式创建、编辑、导入和导出 Excel 电子表格。几乎可以在任何地方部署。 创建、加载、编辑和保存 Excel 电子表格 保存为 .XLSX、PDF、HTML、CSV 和 JSON 基于具有零 Excel 依赖性的 Excel 对象模型 在本地、内部或云…

利用Facebook群组和页面打造忠实粉丝基础

社交媒体的崛起改变了我们与世界互动的方式&#xff0c;而Facebook作为其中的佼佼者&#xff0c;不仅让我们能够与朋友、家人保持联系&#xff0c;还提供了许多机会用于商业营销。利用Facebook群组和页面来打造忠实粉丝基础是许多品牌成功的关键之一。 一、创建一个引人注目的F…

bat脚本

bat脚本 bat脚本就是DOS批处理脚本&#xff0c;就是将一系列DOS命令按照一定顺序排列而形成的集合&#xff0c;运行在windows命令行环境上。这个文件的每一行都是一条DOS命令 在命令提示下键入批处理文件的名称&#xff0c;或者双击该批处理文件&#xff0c;系统就会调用Cmd.…

Java每日一练(20230513) 输出最值、盛水容器、旋转数组II

目录 1. 输出最值 ※ 2. 盛最多水的容器 &#x1f31f;&#x1f31f; 3. 搜索旋转排序数组 II &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 输出最值…

深度学习环境配置系列文章(二):Anaconda配置Python和PyTorch

深度学习环境配置系列文章目录 第一章 专业名称和配置方案介绍 第二章 Anaconda配置Python和PyTorch 第三章 配置VS Code和Jupyter的Python环境 第四章 配置Windows11和Linux双系统 第五章 配置Docker深度学习开发环境 第二章文章目录 深度学习环境配置系列文章目录前言一&…

VMware常用操作

一、vsphere linux虚拟机在线添加磁盘 1、编辑虚拟机设置 添加硬盘 后面步骤下一步即可 然后ssh 到虚拟机 查看/sys/class/scsi_host/ 有几个hostx按下列方法在线认磁盘 echo "- - -" > /sys/class/scsi_host/host2/scan 1、认到磁盘后创建pv pvcreate /dev/sdb …

【C++ 入坑指南】(04)基础语法

文章目录 一、注释二、变量三、常量四、关键字五、标识符 一、注释 作用&#xff1a;在代码中加一些说明和解释&#xff0c;方便自己或其他程序员阅读代码。 C 中有两种注释&#xff1a; 单行注释&#xff1a; // 描述信息 通常放在一行代码的上方&#xff0c;或者一条语句的…

key_vector详解

key_vector是linux网络路由时&#xff0c;非常重要的一个结构&#xff0c;其定义如下&#xff1a; struct key_vector { t_key key; unsigned char pos; /* 2log(KEYLENGTH) bits needed */ unsigned char bits; /* 2log(KEYLENGTH) bits needed */ unsigned char slen; 子网长…

kubernetes❀资源管理

kubernetes❀资源管理 3. 资源管理3.1 资源管理介绍3.2 YAML语言介绍3.3 资源管理方式3.3.1 命令式对象管理3.3.2 命令式对象配置3.3.3 声明式对象配置 3. 资源管理 3.1 资源管理介绍 在kubernetes中&#xff0c;所有的内容都抽象为资源&#xff0c;用户需要通过操作资源来管…

Git advanced高级操作

这篇文章是继Git概念介绍&#xff0c;常用命令与工作流程整理 配图_TranSad的博客-CSDN博客 之后的一些补充&#xff0c;学习总结一些额外Git操作中的比较常用的操作。所以这篇文章假设你已经有了前面的基础&#xff0c;我就直接说一些没有提到过的部分。 Detached HEAD 在G…

镜面反射BRDF模型(Specular BRDF)

利用这些假设&#xff08;局部光学平坦表面&#xff0c;没有相互反射&#xff09;&#xff0c;可以很容易推导出一个被称为Microfacet Cook-Torrance BRDF的一般形式的Specular BRDF项。此Specular BRDF具有以下形式&#xff1a; 其中&#xff1a; D(h) : 法线分布函数 &#…

数据结构与算法十一 图的入门

一 图的入门 1.1 图的实际应用 在现实生活中&#xff0c;有许多应用场景会包含很多点以及点点之间的连接&#xff0c;而这些应用场景我们都可以用即将要学习的图这种数据结构去解决。 地图&#xff1a; 我们生活中经常使用的地图&#xff0c;基本上是由城市以及连接城市的道…