信号-3-信号处理、可重入函数与`volatile`关键字总结

news2024/11/26 2:34:11

信号处理是操作系统中的一个重要机制,它允许进程在运行期间响应外部事件,并作出相应的处理。为了处理信号,程序员需要理解如何设置信号处理器,如何管理信号的屏蔽与阻塞,以及信号的递送机制。本文将结合操作系统中的信号处理、可重入函数、以及volatile关键字等概念,进行详细的分析和总结。

一、信号捕捉与 sigaction 机制

1. 信号处理简介

在类 Unix 系统中,信号是一种用于通知进程发生特定事件的机制。信号可以由操作系统发送,也可以由进程发送。信号可以用于进程间通信、错误处理以及通知等。

  • 信号处理函数:当进程接收到信号时,操作系统会根据设定的信号处理函数(Signal Handler)来响应该信号。通过捕捉并处理信号,程序可以在接收到信号时执行特定的操作。

2. 使用 sigaction 配置信号处理器

sigaction 是一种设置信号处理函数的方式,提供了比 signal 更强大的功能。sigaction 是一个结构体,其中包含了设置信号处理函数的各项信息。

struct sigaction 结构体

struct sigaction {
    void     (*sa_handler)(int);    // 信号处理函数
    void     (*sa_sigaction)(int, siginfo_t *, void *); // 扩展的信号处理函数
    sigset_t sa_mask;                // 屏蔽信号集,在信号处理期间会被阻塞
    int      sa_flags;               // 信号的行为标志
    void     (*sa_restorer)(void);  // 保留字段,不常用
};
  • sa_handler:指向信号处理函数的指针。此函数将在信号到达时执行。
  • sa_mask:指示在处理该信号时,需要屏蔽哪些信号。
  • sa_flags:指定信号处理的行为。例如,SA_SIGINFO 使得信号处理函数接收额外的信号信息。
  • sa_restorer:一般不需要关注,是为了兼容旧的接口。

sigaction 与信号阻塞:

  • 信号嵌套:操作系统不允许信号处理方法进行嵌套,即一个信号正在处理时,系统会自动屏蔽该信号,直到当前信号处理完成。嵌套信号的屏蔽是由操作系统自动完成的,而无需程序员干预。
  • sa_mask 的作用sa_mask 用来指定在信号处理期间需要屏蔽的其他信号。例如,如果你处理 SIGINT 信号时不希望收到 SIGTERM,可以在 sa_mask 中屏蔽 SIGTERM

3. pending 信号和清零时机

在某些情况下,信号可能会在处理信号时被再次递送到进程。pending 信号是指操作系统在信号处理期间接收到的所有待处理的信号。操作系统会在信号处理函数执行之前清空 pending 信号队列。这样做是为了避免一个信号处理期间再次接收同样的信号。

然而,如果一个信号的处理函数在执行过程中接收到相同的信号,并且该信号没有被阻塞,则在处理完当前信号后,操作系统会继续递送该信号。信号的递送通常会按照先进先出(FIFO)的顺序进行。

二、可重入函数与不可重入函数

1. 可重入与不可重入

一个函数被称为可重入函数(reentrant)是指它可以在多次调用之间并行执行而不会出现冲突或错误。当一个函数在执行期间,如果被中断(例如:在信号处理中被调用),能够正确地重新进入并执行,而不会影响原来的执行状态。

  • 不可重入函数:如果一个函数在执行过程中,其状态依赖于共享资源(例如:全局变量或静态变量),当该函数被再次调用时,可能会导致数据冲突或错误,称为不可重入函数。
  • 可重入函数:如果一个函数在执行过程中完全依赖于局部资源(例如:局部变量、栈空间等),则在多个执行流之间调用时,不会发生资源冲突,称为可重入函数。

2. 判断函数是否可重入

  • 全局资源/共享资源:不可重入
    如果函数中涉及对全局变量、静态变量或外部资源(如文件、网络连接等)的操作,并且这些资源是共享的,那么该函数就是不可重入的。

  • 局部资源:可重入
    如果函数只依赖于局部变量,且没有使用任何共享资源,函数就是可重入的。

3. 函数名后缀 _r(线程安全)

有些函数的实现可能是不可重入的,为了提供可重入的变体,许多标准库函数提供了以 _r 结尾的版本(例如 strtok_r)。这些带有 _r 后缀的函数通常会通过将共享资源变为局部资源的方式,解决不可重入问题,使其线程安全和可重入。

4. 可重入函数的例子

  • 可重入strncpy()(只要没有改变共享资源)、malloc()(不会改变全局状态)、memcpy()(只使用栈空间)。
  • 不可重入rand()strtok()(修改全局状态,可能引发冲突)。

三、volatile 关键字

1. volatile 的含义

与register相反

volatile 是 C 语言中的一个关键字,用于告诉编译器某个变量的值可能会被外部环境或其他程序所修改,通常用于避免编译器优化掉某些变量的读取或写入操作。

  • 防止优化:在多线程或信号处理程序中,某些变量的值可能被外部事件改变,如信号处理程序或者硬件中断。因此,我们需要使用 volatile 关键字来告诉编译器每次都从内存中读取该变量的值,而不是使用寄存器缓存的值。

  • 内存可见性volatile 确保每次访问该变量时都从内存中读取最新的值,而不是使用寄存器的缓存副本。这在并发环境下尤为重要。

优化指令如下
其中, -o3为三级优化, 从1-3,优化成都加深。-o0为不优化

gcc file -o3

2. 使用场景

  • 多线程:在多线程环境下,如果一个线程修改了某个全局变量,其他线程需要能立即看到该变量的变化,这时可以使用 volatile 关键字来确保变量不会被优化。
  • 信号处理:在信号处理程序中,如果信号处理程序修改了某个变量,而主程序需要监视这个变量,必须使用 volatile 来确保该变量的值不会被优化掉。

3. 示例代码

volatile int flag = 0; //volatile使用方法

void signal_handler(int sig) {//信号捕捉执行流
    flag = 1;  // 设置标志,表示信号到达
}

int main() {//主执行流
    signal(SIGINT, signal_handler);
    
    while (!flag) {
    	pause();//等待信号
        // 忙等,等待信号
    }

    printf("Received signal, exiting...\n");
    return 0;
}

4. 为什么 volatile 不会退出

如果不使用 volatile,编译器可能会优化掉 flag 的检查,因为它没有在循环中被修改。通过使用 volatile,确保每次都从内存读取 flag,防止编译器优化掉对 flag 的访问。

四、SIGCHLD 信号

SIGCHLD 是操作系统中与子进程相关的信号。当子进程退出或停止时,父进程会收到 SIGCHLD 信号。父进程可以捕捉这个信号并处理子进程退出的情况。

  • 默认行为:默认情况下,操作系统会在子进程退出时,将其状态保留在进程表中,直到父进程调用 wait() 系统调用以读取子进程的退出状态。
  • 捕捉 SIGCHLD:如果父进程捕捉到 SIGCHLD 信号,通常会通过 wait()waitpid() 等系统调用来收集子进程的退出状态。

板书笔记

在这里插入图片描述

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

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

相关文章

深度学习-图像评分实验(TensorFlow框架运用、读取处理图片、模型建构)

目录 0、实验准备 ①实验环境 ②需要下载的安装包 ③注意事项(很关键,否则后面内容看不懂) ④容易出现的问题 1、查看数据并读取数据。 2、PIL库里的Image包进行读取(.resize更改图片尺寸,并将原始数据归一化处…

【Linux系统】—— 基本指令(二)

【Linux系统】—— 基本指令(二) 1 「alias」命令1.1 「ll」命令1.2 「alias」命令 2 「rmdir」指令与「rm」指令2.1 「rmdir」2.2 「rm」2.2.1 「rm」 删除普通文件2.2.2 「rm」 删除目录2.2.3 『 * 』 通配符 3 「man」 指令4 「cp」 指令4.1 拷贝普通…

面向对象技术简述(含设计模式)

6.9.2 面向对象技术 面向对象 对象 分类 继承 通过消息的通信 面向对象 对象 分类 继承 通过消息的通信 面向对象对象分类继承通过消息的通信其中包括: 对象 运行的实体;既包含属性/数据,又包含方法/行为/操作数据的函数;…

【信号处理】基于联合图像表示的深度学习卷积神经网络

Combined Signal Representations for Modulation Classification Using Deep Learning: Ambiguity Function, Constellation Diagram, and Eye Diagram 信号表示 Ambiguity Function(AF) 模糊函数描述了信号的两个维度(dimensions):延迟(delay)和多普勒(Doppler)。 …

【C++练习】两个实型数的加法运算

题目: 编写一个C程序,实现两个实型数的加法运算并输出结果。 要求: 定义一个函数 dadd,该函数接收两个 double 类型的参数,并返回它们的和。在 main 函数中,提示用户输入两个实型数(double 类…

【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)

博主说明:本文项目编号 T 061 ,文末自助获取源码 \color{red}{T061,文末自助获取源码} T061,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

Sql面试题二:请查询出用户连续三天登录的所有数据记录

问题: 现有用户登录记录表,请查询出用户连续三天登录的所有数据记录 id dt 1 2024-04-25 1 2024-04-26 1 2024-04-27 1 2024-04-28 1 2024-04-30 1 2024-05-01 1 2024-05-02 1 2024-05-04 1 2024-05-05 2 2…

科研绘图系列:R语言分组堆积图(grouped stacked barplot)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包准备画图主题数据链接导入数据画图数据准备图例图1图2合并图系统信息介绍 分组堆积图(Grouped Stacked Bar Chart)是一种数据可视化图表,它结合了分组柱状图和堆积柱状图…

世界技能竞赛大数据应用开发环境1:1还原

集群情况 模块A搭建环境,在容器中搭建大数据平台 Pc机,安装安装比赛需要软件 模块B中使用idea快速开发完成数据处理 模块E包含了接口数据,使用vs code快速搭建vue数据可视化

【网络协议大花园】应用层 http协议的使用小技巧,用好了都不用加班,效率翻两倍(下篇)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人…

SpringBoot源码解析(一)

SpringBoot自动装配原理 SpringBootApplication注解 我们在使用SpringBoot时,通常使用的是SpringBootApplication这个注解,比如: 而这个注解的定义为下图,可以发现这个注解上有另外三个注解:SpringBootConfiguration…

流类库与输入输出

来源:《C语言程序设计》 像C语言一样,C语言也没有输入输出语句。 但C标准库中有一个面向对象的输入输出软件包,即I/O流类库。 流是I/O流类的中心概念。 ------ I/O流类库是C语言中I/O函数在面向对象的程序设计方法中的一个替换产品。 -…

k8s图形化显示(KRM)

在master节点 kubectl get po -n kube-system 这个命令会列出 kube-system 命名空间中的所有 Pod 的状态和相关信息,比如名称、状态、重启次数等。 systemctl status kubelet #查看kubelet状态 yum install git #下载git命令 git clone https://gitee.com/duk…

理解鸿蒙app 开发中的 context

是什么 Context是应用中对象的上下文,其提供了应用的一些基础信息,例如resourceManager(资源管理)、applicationInfo(当前应用信息)、dir(应用文件路径)、area(文件分区…

ML1:sklearn env

sklearn: 中文参考: https://scikit-learn.cn/stable/modules/linear_model.html#ordinary-least-squares https://scikit-learn.org.cn/view/4.html ——》为主,不懂地方参考上面中文以及下面英文 英文参考: https://scikit…

五分钟入门双拼!

‍这是从零开始学双拼的第一篇:概述 双拼的原理 如果你使用全拼,想要完整敲出一个字的读音,需要敲出这个字拼音的每个字母。 虽然简拼能简化一点步骤,但除非是很常见的成语、俗语,否则重码率很高,选词很…

基于STM32的智能充电桩:集成RTOS、MQTT与SQLite的先进管理系统设计思路

一、项目概述 随着电动车的普及,充电桩作为关键基础设施,其智能化、网络化管理显得尤为重要。本项目旨在基于STM32微控制器开发一款智能充电桩,能够实现高效的充电监控与管理。项目通过物联网技术,提供实时数据监测、远程管理、用…

毕业后如何查找获取文献

当我们毕业后就无法再使用自己学校的数据库资源了,如果需要查找文献该从哪里获取资源呢?下面这个方法很简单而且有效: 一、首先选对科研工具 文献党下载器,把大量数据库资源整合在一起,直接去文献来源数据库查找获取…

串口接收,不定长数据接收

###1.CUBE-MX配置串口 2.我采用串口中断接收,打开中断接口 3.时钟同样8倍频,1分频,使用内部时钟 打开串口中断 main() { __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 启用空闲中断__HAL_UART_ENABLE_IT(&huart1, UART_IT_R…

2024 高质量 Java 面试题集锦:高级 Java 工程师面试八股汇总

最近感慨面试难的人越来越多了,一方面是市场环境,更重要的一方面是企业对 Java 的人才要求越来越高了。 基本上这样感慨的分为两类人,第一,虽然挂着 3、5 年经验,但肚子里货少,也没啥拿得出手的项目&#x…