Linux-信号3_sigaction、volatile与SIGCHLD
文章目录
- 前言
- 一、sigaction
- __sighandler_t sa_handler;
- __sigset_t sa_mask;
- 二、volatile关键字
- 三、SIGCHLD
- 方法一
- 方法二
前言
本章内容主要对之前的内容做一些补充。
一、sigaction
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
之前我们学过signal来对信号进行捕捉,sigaction也是一个对信号进行捕捉的系统接口函数,不过sigaction要相对复杂一些。
参数 int signum 是要捕捉的信号编号。
参数struct* sigaction 在这里作为输入型参数,是提供给我们的一个结构体指针类型,这里的结构体名和函数名相同。
参数struct sigaction *oldact 在这里作为输出型参数。
那么struct sigaction 里面有什么呢?
struct sigaction{/* Signal handler. */
#ifdef __USE_POSIX199309union{/* Used if SA_SIGINFO is not set. */__sighandler_t sa_handler;/* Used if SA_SIGINFO is set. */void (*sa_sigaction) (int, siginfo_t *, void *);}__sigaction_handler;
# define sa_handler __sigaction_handler.sa_handler
# define sa_sigaction __sigaction_handler.sa_sigaction
#else__sighandler_t sa_handler;
#endif/* Additional set of signals to be blocked. */__sigset_t sa_mask;/* Special flags. */int sa_flags;/* Restore handler. */void (*sa_restorer) (void);};
我们今天主要对函数体内部的sa_handler和sa_mask进行讨论
__sighandler_t sa_handler;
typedef void __signalfn_t(int);
typedef __signalfn_t *__sighandler_t;
根据__sighandler_t的定义,我们可以知道其本质是一个函数指针,所以这里的我们就可以知道其实本质也是像signal一样使用回调函数来进行信号的捕捉。
__sigset_t sa_mask;
typedef __sigset_t sigset_t;
之前我们在学习sigprocmask和sigaddset等信号集接口函数的时候有过接触sigset_t,那么这里的sa_mask是什么呢?
先提出一个观点,在一个信号被处理(递达)过程中,如果同一个信号再次被发送且进入pending表,那么OS是怎样处理的? OS的处理方式是block(阻塞)相同信号,不再重复递达,等到处理完正在被处理的信号再根据情况决定。 而sa_mask在这里的作用就是可以根据其信号集的有效信号,在signum信号正在被处理时,同时阻塞sa_mask的有效信号和其本身信号。
示例代码如下
#include<iostream>
#include<cstdio>
#include<signal.h>
#include<unistd.h>void ShowPending()
{sigset_t pending;sigemptyset(&pending);for (int i = 1; i <= 31; i++){sigpending(&pending);// 通过sigismember来打印我们的pending信号集std::cout << sigismember(&pending, i);}std::cout << std::endl;
}void catchSig(int signum)
{std::cout << "捕捉到" << signum << "信号!" << std::endl; int count = 0;while(1){ShowPending();count++;if(count == 50) break;sleep(5);}
}
int main()
{std::cout << "pid: " << getpid() << std::endl;//1.定义struct sigaction类型struct sigaction act , oldact;//2.mask信号集初始化sigset_t mask;sigemptyset(&mask);//3.mask信号集添加1号,2号,3号, 4号,5号,6号作为有效信号sigaddset(&mask,1);sigaddset(&mask,2);sigaddset(&mask,3);sigaddset(&mask,4);sigaddset(&mask,5);sigaddset(&mask,6);//4.修改act中的数据act.sa_handler = catchSig;act.sa_mask = mask;//5.调用sigactionsigaction(2, &act , &oldact);while(1) sleep(1);return 0;
}
运行结果

二、volatile关键字
我们之前的学习过程中,也提到过编译器会进行优化,例如我们之前讲的拷贝构造和右值引用都有提到过,而volatile主要解决关于编译器优化所导致的问题。
是的,编译器优化在少数情况下是会造成一些问题的。
而Linux中的gcc编译器是有几种不同程度的优化方案的
-O -O0 -O1 -O2 -O3 -Os -Ofast -Og
在使用gcc或g++命令时,上面的选项从左到右,编译时优化程度依次变大。
示例代码如下
#include<iostream>
#include<cstdio>
#include<signal.h>
#include<unistd.h>int flag = 0;void catchSig(int signum)
{std:: cout << flag ;flag = 1;std::cout << "->" << flag <<std::endl;
}int main()
{signal(2, catchSig);while(1){if(flag == 1) break;;}std::cout << "程序正常退出" << std::endl;return 0;
}
这段代码如果使用
g++ -o mysignal mysignal.cc -std=c++11
进行编译
结果则是

这段代码如果使用
g++ -o mysignal mysignal.cc -std=c++11 -O3
进行编译
结果则是

程序不会自动退出。
这是因为在-O3的优化程度下,编译器检测默认执行流不会修改flag的数据,所以这里的cpu寄存器一直储存着原有的flag值0,导致在判断flag时,一直使用寄存器中的0在判断,导致循环无法退出。
现在我们使用volatile来试试
#include<iostream>
#include<cstdio>
#include<signal.h>
#include<unistd.h>volatile int flag = 0;void catchSig(int signum)
{std:: cout << flag ;flag = 1;std::cout << "->" << flag <<std::endl;
}int main()
{signal(2, catchSig);while(1){if(flag == 1) break;;}std::cout << "程序正常退出" << std::endl;return 0;
}

这个时候程序就正常推出了,所以这里volatile的意思就是让告诉编译器不要对flag进行优化,要让寄存器看到内存中的数据!
三、SIGCHLD
SIGCHLD 在子进程停止或者退出时可能收到。
所以我们再学习几种进程等待的方法。
方法一
#include <iostream>
#include <cstdio>
#include <signal.h>
#include <unistd.h>int main()
{signal(SIGCHLD, SIG_IGN);pid_t id = fork();if(id == 0){//子进程sleep(10);exit(0);}//父进程while(1);return 0;
}
将SIGCHLD信号的处理方式变为忽略。

子进程没有僵尸,而是成功回收。
方法二
#include <iostream>
#include <cstdio>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
void catchCHLD(int signum)
{std::cout << "捕捉到SIGCHLD信号!" << std::endl;int pid = 0;while((pid = waitpid(0,nullptr,WNOHANG)) > 0){std::cout << "成功等待" << pid << "号进程" << std::endl;}
}int main()
{signal(SIGCHLD, catchCHLD);pid_t id = fork();if(id == 0){//子进程sleep(10);exit(0);}//父进程while(1);return 0;
}

也同样可以成功回收!
相关文章:
Linux-信号3_sigaction、volatile与SIGCHLD
文章目录 前言一、sigaction__sighandler_t sa_handler;__sigset_t sa_mask; 二、volatile关键字三、SIGCHLD方法一方法二 前言 本章内容主要对之前的内容做一些补充。 一、sigaction #include <signal.h> int sigaction(int signum, const struct sigaction *act,struc…...
STM32 | STM32时钟分析、GPIO分析、寄存器地址查找、LED灯开发(第二天)
STM32 第二天 一、 STM32时钟分析 寄存器:寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成 在计算机领域&#x…...
Python常用语法汇总(一):字符串、列表、字典操作
1. 字符串处理 print(message.title()) #首字母大写print(message.uper()) #全部大写print(message.lower()) #全部小写full_name "lin" "hai" #合并字符串print("Hello, " full_name.title() "!")print("John Q. %s10s&qu…...
Token的奥秘--一起学习吧之token
Token,在计算机科学中,是一个用于表示数据或一段数据的单位。它通常用于加密、身份验证、令牌化等场景,以确保数据的安全性和完整性。在编程语言中,Token通常是指代一段代码或数据的最小单元,例如一个变量、一个操作符…...
FlinkCDC快速搭建实现数据监控
引入依赖 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelV…...
应急布控球远程视频监控方案:视频监控平台EasyCVR+4G/5G应急布控球
随着科技的不断发展,应急布控球远程视频监控方案在公共安全、交通管理、城市管理等领域的应用越来越广泛。这种方案通过在现场部署应急布控球,实现对特定区域的实时监控,有助于及时发现问题、快速响应,提高管理效率。 智慧安防视…...
3.6 C语言和汇编语言混合编程 “每日读书”
在一些嵌入式场合,我们经常看到C程序和汇编程序相互调用,混合编程,如在ARM启动代码中,系统上电首先运行的是汇编代码,等初始化好内存堆栈环境之后,才会跳到C程序中执行,对嵌入式软件进行优化时&…...
利用“定时执行专家”循环执行BAT、VBS、Python脚本——含参数指定功能
目录 一、软件概述 二、VBS脚本执行设置 三、触发器设置 四、功能亮点 五、总结 在自动化办公和日常计算机任务管理中,定时执行脚本是一项非常重要的功能。今天,我将为大家带来一款名为“定时执行专家”的软件的评测,特别是其定时执行VB…...
【算法集训】基础算法:模拟
一、基本理解 顾名思义,就是题目要求做什么,代码中就跟着做就可以。 二、题目练习 1252. 奇数值单元格的数目 根据题目要求列出如下代码。需要注意填充列和行的时候注意下标。 int oddCells(int m, int n, int** indices, int indicesSize, int* in…...
基于SSM的房客源信息管理系统设计与实现
目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 SSM框架 3 1.2 Vue框架 3 1.3 ECharts 3 1.4 JQuery技术 3 1.5 本章小结 4 2系统分析 5 2.1 需求分析 5 2.2 非功能需求 8 2.3 本章小节 8 3 系统设计 9 3.1 系统总体设计 9 3.1.1 系统体系结构 9 3.1.2 系统目录结构 9 3…...
常见数据类型
目录 数据类型 字符串 char nchar varchar varchar2 nvarchar 数字 number integer binary_float binary_double float 日期 date timestamp 大文本数据 大对象数据 Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 数…...
基于vue的联通积分商城数据可视化APP设计与实现
目 录 摘 要 I Abstract II 引 言 1 1 前端技术介绍 3 1.1 前端开发语言 3 1.1.1 HTML5 3 1.1.2 CSS3 3 1.1.3 JavaScript 3 1.2 MVVM开发模式 4 1.3 Vue框架 4 1.4 Axios技术 5 1.5 ECharts 5 1.6 数据库技术 5 1.7 本章小结 6 2 前端开发的分析 7 2.1 功能性需求分析 7 2.2 …...
2024年flink面试真题(一)
(北京)taskManager和slot、task的关系 ? (北京)flink状态太大怎么解决 ? (北京 flink提交方式和运行模式 ? (北京) 怎么提交的实时任务,有多少Job Manager? &…...
Java面试挂在线程创建后续,不要再被八股文误导了!创建线程的方式只有1种
线程创建之源 OK!咱们闲话少叙,直接进入正题,回顾一下通过实现Runnable接口,重写run方法创建线程的方式,真的可以创建一个线程吗?来看下面这段demo。 【代码示例1】 public class Test implements Runnab…...
JavaEE面试题
一、String面试题 1、String s1 "123"; 和 String s2 new String("123");的区别 在Java中,"String s1 "123";"和"String s2 new String("123");"这两行代码有一些重要的区别: "…...
探索macOS上的最佳MySQL客户端工具
在数据库管理和开发的世界里,选择一个高效、功能全面的客户端工具对于提升工作效率至关重要。尤其对于使用 macOS 的开发者来说,一个好的 MySQL 客户端不仅可以简化数据库操作,还能提供强大的数据分析和管理功能。本文将介绍几款适用于 macOS…...
[Android] MediaPlayer SDK API glance
参考: https://developer.android.com/reference/android/media/MediaPlayer 如何使用MediaPlayer SDK: https://developer.android.com/media/platform/mediaplayer 概述: 音视频的 playback。创建 MediaPlayer 的线程必须和调用 SDK 接口…...
原始手写helloworld并打jar包允许
1.创建文件夹test统一在其中操作 2.创建hello.java文件 【hello.txt改属性为hello.java】并在里面添加代码 public class hello {public static void main(String[] args) {System.out.println("hello world");} } 注意:类名与文件名一致 然后运行…...
maven 的安装与配置(Command ‘mvn‘ not found)修改配置文件后新终端依旧无法识别到 mvn 命令
下载 maven 安装包 wget https://dlcdn.apache.org/maven/maven-3/3.9.4/binaries/apache-maven-3.9.4-bin.tar.gz 解压 apache-maven-3.9.4-bin.tar.gz tar -zxvf apache-maven-3.9.4-bin.tar.gz 找到文件解压到的位置,由于解压时我们没有指定路径,因…...
Pycharm无法粘贴外部文本问题
Pycharm无法粘贴外部文本问题 百度找了好多是因为安装了vim,最后发现是因为pycharm粘贴框存在了很多内容导致 操作方法: 1、清理所有缓存的复制内容 ctrlshiftV 可以看到编译器所有缓存下来的复制文本 2、ctrlA然后delete 解决:此时再复…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...
