Linux基础内容(23)—— 信号补充与多线程交接知识

news2024/11/24 11:33:32

Linux基础内容(22)—— 信号_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/130835485

 目录

1.可重入函数

1.情况假设

2.volatile

3.SIGCHLD信号

1.SIGCHLD介绍

2.信号的确认

3.wait的处理


1.可重入函数

1.情况假设

1.我们实现了一个main函数,是关于链表头插的逻辑。也就是说当我们调用该函数,指定的链表通过这个函数,new出一个新的节点,头插到链表中,头节点重新更新为当前节点

2.我们先描述一下这个头插的过程,就是先将节点new出来,随后将节点的next指向链表,最后将头节点更新

3.现在我们将注意放在信号处理逻辑上,首先我们先得到一个信号处理的函数,该函数的处理逻辑与new新节点头插链表完全一致。即当指定一个定义的信号后,信号会被捕获执行new新节点进行头插的逻辑

4.随后当执行头插函数过程中,当这个函数执行到将节点的next指向链表后,就接收到指定的信号进行处理逻辑,那么此时我们会发现一个事实,我们的链表分叉了。

1.像上例这样,insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入,insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为不可重入函数

2.如果一个函数只访问自己的局部变量或参数,则称为可重入函数

3.调用了malloc或free,因为malloc也是用全局链表来管理堆的。调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构。使用这些都是不可重入函数

2.volatile

以下是一段关于信号来进行退出进程的代码

#include<stdio.h>
#include<signal.h>

int quit=0;

void handler(int signo)
{
    printf("%d 号信号,正在被捕捉\n",signo);
    printf("quit: %d",quit);
    quit=1;
    printf("-> %d",quit);
}

int main()
{
    signal(2,handler);
    while(!quit);
    printf("正常退出\n");
    return 0;
}

1.正常编译该代码后执行,会发现进程一直循环着,一旦我们对进程传入2号信号后,该循环会被正常退出.这样的结果是可预见的

2.不过,我们需要介绍编译器优化。默认的编译器优化级别其实不高,但是我们可以手动调搞优化级别,在makefile中编译添加 -Ox(x为优化级别)。那下面我们对该段代码重新编译-O3级别,随后执行代码我们会发现:最开始代码仍然在循环中,说明此时quit=,随后信号2输入进程中,进程打印quit由0变1,但是此时我们发现进程并没有退出。随后继续不断输入2信号,quit由1变1,但是进程始终没有退出,代码并没有按照我们本来的意愿进行执行正常退出。

原因:

1.一个数据的流程是先由cpu在内存中得到对应的值,随后进行一系列操作cpu得到最终的结果将值返回给内存

2..对于默认优化的编译,其数值其实本来是在内存中,然后当while循环判断时,quit在内存中会将值传入cpu,cpu判断后,进行循环;一旦信号递达后,quit在内存中就被修改为1了,那么此时while判断时,cpu会从内存中得到quit的值,此时cpu的判断循环结束,整个进程在之后也就结束了

3.不过被优化过的编译,会认为quit这个值对于编译器而言就是只需要进行判断的,不需要返回给内存,那么自然在qiut被定义后,这个0值就一直在cpu的寄存器中存着,但是每一次的信号递达都修改的是内存中的quit值,但是内存的值不代表cpu中寄存器的值,循环结束的条件依然是quit在寄存器中的值,寄存器中的值至始至终都没有变过,循环一直进行。所以出现了我们即使信号递达后修改了当前的值也没有结束进程的奇怪思路

那么此时volatile就能被应用了

// volatile:保持内存可见性 
volatile int quit=0;

void handler(int signo)
{
    printf("%d 号信号,正在被捕捉\n",signo);
    printf("quit: %d",quit);
    quit=1;
    printf("-> %d",quit);
}

int main()
{
    signal(2,handler);
    while(!quit);
    printf("正常退出\n");
    return 0;
}

volatile:保持内存可见性,即每次数据都从内存中读取,而不是在cpu的寄存器中读。

执行该代码,优化后也依然是我们想要的第一种结果。

3.SIGCHLD信号

1.SIGCHLD介绍

父进程wait等待子进程并不是白白的硬等。子进程在要退出前会变成僵尸进程,在变成僵尸进程时,会像父进程发送SIGCHLD信号,使得父进程知道子进程死亡了。SIGCHLD的默认操作是系统层面的忽略(Ign)。

2.信号的确认

 写一段代码验证

void handler(int signo)
{
    printf("%d 号信号,正在被捕捉\n",signo);
    while(1)
    {
        pid_t ret = waitpid(-1, NULL, WNOHANG);
        if(ret == 0) break;
    }
}

int main()
{
    signal(SIGCHLD,handler);
    printf("父进程 pid:%d ppid:%d\n",getpid(),getppid());
    pid_t id = fork();
    if(id==0)
    {
        printf("子进程 pid:%d ppid:%d\n",getpid(),getppid());
        exit(1);
    }
    while(1) sleep(1);
    return 0;
}

结果确实是说明的那样。

3.wait的处理

1.如果我们创造了一批的子进程并且全部的子进程是同一时间结束,那么父进程的waitpid就必须循环式的等待,因为只等待一次就只能回收一个,所以是while中循环的waitpid(-1, NULL, 0)回收任意的子进程。-1是指回收任意的子进程宏定义

2.如果我们想要回收一批创建好的子进程,不过这次我们的子进程并不是所有回收,只是回收一部分。那么此时的我们不能waitpid(-1, NULL, 0)这样等待,因为这样的等待父进程不会进行其他操作,并且回收完了父进程也不会知道,依然回收,最后导致父进程难被回收。那么我们想要挂起等待,waitpid(-1, NULL, WNOHANG),确保父进程不被挂起

3.当然,我们也可以直接选择用signal信号进行回收子进程,其做法很简单,就是将signal信号接收SIGCHLD后对信号手动忽略(SIG_IGN),即signal(SIGCHLD, SIG_IGN)。此时子进程被回收的工作就不用我们手动wait,系统自动的回收了。不过我们不会得到子进程的退出状态码,这一点需要注意

4.手动的SIG_IGN和信号自己的Ign的忽略不是同一个忽略。系统的Ign在内核会有其他的操作,我们用户调用后就能得到对应的状态码;但是手动的SIG_IGN不同,它是一个宏定义,它内部是将一个地址宏定义了,就是访问地址为1的空间

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

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

相关文章

插件 - 通过SPI方式实现插件管理

文章目录 SPI概念基本原理使用步骤优点缺点Code真实使用场景案例JDBC(Java Database Connectivity)Servlet API日志框架SPI概念 SPI(Service Provider Interface)是Java提供的一种服务扩展机制,它允许应用程序在运行时动态加载和发现提供者(Providers),并与它们进行交…

Proteus仿真之UART通信(点亮LED灯)

1.UART通信简介&#xff1a;通用异步收发传输器UART(Universal Asynchronous Receiver/Transmitter)是负责处理数据总线和串口之间的串/并通信的设备。UART通信规定了数据帧的格式&#xff1a;起始位、数据位、校验位、停止位等。UART异步通信只需要通信双方设置好数据帧的格式…

房屋装修选择自装,如何寻找水电工人,比价并施工(水电阶段)

环境&#xff1a; 地点&#xff1a;杭州 装修类型&#xff1a;自装 面积&#xff1a;建面135平方 进度&#xff1a;水电阶段 问题描述&#xff1a; 房屋装修选择自装&#xff0c;如何寻找水电工人&#xff0c;比价并施工 解决方案&#xff1a; 一、了解水电相关知识 水…

Python3+RIDE+RobotFramework自动化测试框架搭建

Python2.7已于2020年1月1日开始停用&#xff0c;之前RF做自动化都是基于Python2的版本。 没办法&#xff0c;跟随时代的脚步&#xff0c;我们也不得不升级以应用新的控件与功能。 升级麻烦&#xff0c;直接全新安装。 一、Python安装 最新版Python下载地址&#xff1a;http…

Qt连接Access数据库

Qt自带有QODBC驱动&#xff08;封装了ODBC驱动接口&#xff09;&#xff0c;通过windows平台上提供的ODBC驱动访问支持ODBC的数据库&#xff0c;如Ms Access、SQL Server等 (Windows XP 自带有Access和SQL Server的ODBC Driver)。我们就用QODBC对Access数据库进行访问。 Acces…

别再瞎搞了,耳朵都竖起来听我说,新手小白开发应该如何选择最合适你的JetBrains IDE版本类型和版本号! 今天一次性给你说清楚!

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&#x1…

windows环境下搭建redis集群

下面记录一下windows10环境下搭建redis3主3从集群&#xff0c;将过程分享出来&#xff0c;仅供学习研究使用。 1、redis集群 Redis集群关键点就是去掉中心化(与哨兵模式的区别)&#xff0c;当主机宕机&#xff0c;从节点回自动升级为主节点&#xff0c;具体请参考官网或相关大…

机器学习——KNN算法(手动代码,含泪)

徒手实现代码的过程&#xff0c;真是含泪和心酸&#xff0c;浪费了生命中的三天&#xff0c;以及工作中的划水一小时 终于滤清思路后&#xff0c;自己实现了KNN 都说KNN是最基础&#xff0c;最简单的分类器 放屁&#xff01;骗纸&#xff01;&#xff01;&#xff01;它的想法是…

第八章——向量代数与空间解析几何

目录 一、运算公式 二、平面的法线向量 注&#xff1a;加粗体为向量 一、运算公式 1.若a//b&#xff0c;那么aλb 若a⊥b&#xff0c;那么a*b0 2.若A(x1,y1,z1)&#xff0c;B(x2,y2,z2) 中点坐标&#xff1a;AB中点M(x1x2/2,y1y2/2,z1z2/2) 两点间的距离和模的计算&#x…

第3章 信息系统治理

文章目录 3.1.1 IT治理基础1. IT治理的驱动因素2. IT治理的目标价值3. IT治理的管理层次 3.1.2 IT治理体系1. IT治理关键决策2. IT治理体系框架3. IT治理核心内容4. IT治理机制经验&#xff08;建立IT治理机制的原则&#xff1a;简单、透明、适合&#xff09; 3.1.3 IT治理任务…

工作流引擎Flowable

这里写目录标题 1.Flowable基础1.1 入门学习 2.流程图设计器2.1 FlowableUI2.1.1 绘制流程图 1.Flowable基础 官方手册 1.1 入门学习 一、依赖 <dependencies><dependency><groupId>org.flowable</groupId><artifactId>flowable-engine</…

jenkins——Git版本管理

这里写目录标题 一、Jenkins Git 版本管理1、Git 的集成2、在执行job的机器上安装好Git3、无法连接仓库&#xff0c;问题解决解决方法1&#xff1a;&#xff08;不推荐&#xff09;1、把仓库设置成公开的&#xff0c;然后重新添加仓库地址 解决方法2&#xff1a;通过凭证的方式…

打破Spring的垄断,云原生Java框架Micronaut

文章目录 什么是Micronaut&#xff1f;Micronaut的功能特性相较于Spring的优势 Micronaut框架的使用安装Micronaut cli创建Micronaut项目 Micronaut应用的部署micronaut反应式编程 MCNU云原生&#xff0c;文章首发地&#xff0c;欢迎微信搜索关注&#xff0c;更多干货&#xff…

基于springboot的文件的上传到本地和云上传(阿里云)

1.文件上传 1.介绍 文件上传&#xff0c;是指将本地图片、视频、音频等文件上传到服务器&#xff0c;供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛&#xff0c;我们经常发微博、发微信朋友圈都用到了文件上传功能。 2.前端的文件上传–form表单 将静态的页面…

接口自动化测试面试问题及答案

目录 1.请问你是如何做接口测试的&#xff1f; 2.接口测试如何设计测试用例&#xff1f; 3.接口测试执行中需要比对数据库吗&#xff1f; 4.接口测试质量评估标准是什么&#xff1f; 5.接口产生的垃圾数据如何清理 6.其他接口要先获取接口信息&#xff0c;如何让登录的接口…

化工园区人员全过程轨迹化安全解决方案

1、项目背景 化工园区化工厂是生产安全重点单位&#xff0c;对人员定位管理需求强烈。对人员定位主要需求是&#xff1a;一般区域人数统计、人员轨迹、重点区域人员实时精准定位。 华安联大安全化工园区人员全过程轨迹化安全解决方案通过人员实时定位管理、移动轨迹追溯、险情…

《项目实战》构建SpringCloud alibaba项目(二、构建微服务鉴权子工程store-authority-service)

系列文章目录 构建SpringCloud alibaba项目&#xff08;一、构建父工程、公共库、网关&#xff09; 构建SpringCloud alibaba项目&#xff08;二、构建微服务鉴权子工程store-authority-service&#xff09; 文章目录 系列文章目录前言1、在公共库增加 UserInfo类2、微服务鉴权…

初识SLAM

SLAM的作用 想象一个叫小萝卜的机器人&#xff0c;小萝卜在未知环境走&#xff0c;肯定想让小萝卜在脑海中记住两件事&#xff1a; 1. 我在什么地方&#xff1f;——定位。 2. 周围环境是什么样&#xff1f;——建图。 这就和我们逛一个旅游景点一样&#xff0c;我们会潜意识…

清华青年AI自强作业hw3_3:用NN网络拟合MNIST手写数字分类

清华青年AI自强作业hw3_3&#xff1a;用NN网络拟合MNIST手写数字分类 实现过程具体思路多分类网络模型训练结果分析 相关链接 一起学AI系列博客&#xff1a;目录索引 hw3_3&#xff1a;用NN网络拟合MNIST手写数字分类 体会神经网络设计和TF框架编程 对比hw3_1两者的模型、效果…

CLIP和GPT

CLIP CLIP下游应用&#xff1a;VQGAN、DALL-ECLIP-Event:Connecting Text and Images with Event StructuresHierarchical Text-Conditional Image Generation with CLIP LatentsGPT系列算法GPT-1&#xff1a;GPT-2&#xff1a;GPT-3&#xff1a;GPT-3应用&#xff1a;Evaluati…