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

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时钟分析 寄存器&#xff1a;寄存器的功能是存储二进制代码&#xff0c;它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码&#xff0c;故存放n位二进制代码的寄存器&#xff0c;需用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&#xff0c;在计算机科学中&#xff0c;是一个用于表示数据或一段数据的单位。它通常用于加密、身份验证、令牌化等场景&#xff0c;以确保数据的安全性和完整性。在编程语言中&#xff0c;Token通常是指代一段代码或数据的最小单元&#xff0c;例如一个变量、一个操作符…...

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应急布控球

随着科技的不断发展&#xff0c;应急布控球远程视频监控方案在公共安全、交通管理、城市管理等领域的应用越来越广泛。这种方案通过在现场部署应急布控球&#xff0c;实现对特定区域的实时监控&#xff0c;有助于及时发现问题、快速响应&#xff0c;提高管理效率。 智慧安防视…...

3.6 C语言和汇编语言混合编程 “每日读书”

在一些嵌入式场合&#xff0c;我们经常看到C程序和汇编程序相互调用&#xff0c;混合编程&#xff0c;如在ARM启动代码中&#xff0c;系统上电首先运行的是汇编代码&#xff0c;等初始化好内存堆栈环境之后&#xff0c;才会跳到C程序中执行&#xff0c;对嵌入式软件进行优化时&…...

利用“定时执行专家”循环执行BAT、VBS、Python脚本——含参数指定功能

目录 一、软件概述 二、VBS脚本执行设置 三、触发器设置 四、功能亮点 五、总结 在自动化办公和日常计算机任务管理中&#xff0c;定时执行脚本是一项非常重要的功能。今天&#xff0c;我将为大家带来一款名为“定时执行专家”的软件的评测&#xff0c;特别是其定时执行VB…...

【算法集训】基础算法:模拟

一、基本理解 顾名思义&#xff0c;就是题目要求做什么&#xff0c;代码中就跟着做就可以。 二、题目练习 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面试真题(一)

&#xff08;北京&#xff09;taskManager和slot、task的关系 ? &#xff08;北京&#xff09;flink状态太大怎么解决 ? &#xff08;北京 flink提交方式和运行模式 ? &#xff08;北京&#xff09; 怎么提交的实时任务&#xff0c;有多少Job Manager&#xff1f; &…...

Java面试挂在线程创建后续,不要再被八股文误导了!创建线程的方式只有1种

线程创建之源 OK&#xff01;咱们闲话少叙&#xff0c;直接进入正题&#xff0c;回顾一下通过实现Runnable接口&#xff0c;重写run方法创建线程的方式&#xff0c;真的可以创建一个线程吗&#xff1f;来看下面这段demo。 【代码示例1】 public class Test implements Runnab…...

JavaEE面试题

一、String面试题 1、String s1 "123"; 和 String s2 new String("123");的区别 在Java中&#xff0c;"String s1 "123";"和"String s2 new String("123");"这两行代码有一些重要的区别&#xff1a; "…...

探索macOS上的最佳MySQL客户端工具

在数据库管理和开发的世界里&#xff0c;选择一个高效、功能全面的客户端工具对于提升工作效率至关重要。尤其对于使用 macOS 的开发者来说&#xff0c;一个好的 MySQL 客户端不仅可以简化数据库操作&#xff0c;还能提供强大的数据分析和管理功能。本文将介绍几款适用于 macOS…...

[Android] MediaPlayer SDK API glance

参考&#xff1a; https://developer.android.com/reference/android/media/MediaPlayer 如何使用MediaPlayer SDK&#xff1a; https://developer.android.com/media/platform/mediaplayer 概述&#xff1a; 音视频的 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");} } 注意&#xff1a;类名与文件名一致 然后运行…...

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 找到文件解压到的位置&#xff0c;由于解压时我们没有指定路径&#xff0c;因…...

Pycharm无法粘贴外部文本问题

Pycharm无法粘贴外部文本问题 百度找了好多是因为安装了vim&#xff0c;最后发现是因为pycharm粘贴框存在了很多内容导致 操作方法&#xff1a; 1、清理所有缓存的复制内容 ctrlshiftV 可以看到编译器所有缓存下来的复制文本 2、ctrlA然后delete 解决&#xff1a;此时再复…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...