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

lv5 嵌入式开发-10 信号机制(下)

目录

1 信号集、信号的阻塞

2 信号集操作函数

2.1 自定义信号集

2.2 清空信号集

2.3 全部置1

2.4 将一个信号添加到集合中

2.5 将一个信号从集合中移除

2.6 判断一个信号是否在集合中

2.7 设定对信号集内的信号的处理方式(阻塞或不阻塞)

2.8  使进程挂起(暂停执行)直到收到一个信号

2.9 更改进程的信号屏蔽字,并等待一个特定的信号到来


掌握:信号集和信号屏蔽

1 信号集、信号的阻塞

应用:

有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延

时一段时间去调用信号处理函数。这种情况可以通过阻塞信号实现。

信号的阻塞概念

信号的”阻塞“是一个开关动作,指的是阻止信号被处理,但不是阻止信号产生。

信号的状态:

信号递达(Delivery ):实际信号执行的处理过程(3种状态:忽略,执行默认动作,捕获)

信号未决(Pending):从产生到递达之间的状态(挂起)

下图表示了,每一个任务控制块都有一个挂起信号集(可读)和信号屏蔽字(可写可读)。信号屏蔽置1,代表忽略该信号的到来

2 信号集操作函数

2.1 自定义信号集

sigset_t set; 

自定义信号集。  是一个  64bit  128bit的数组。

2.2 清空信号集

sigemptyset(sigset_t *set);	

代表接收所有信号

2.3 全部置1

sigfillset(sigset_t *set);	

接收全部信号

2.4 将一个信号添加到集合中

sigaddset(sigset_t *set, int signum);	

接收某一个位的信号

2.5 将一个信号从集合中移除

sigdelset(sigset_t *set, int signum);	

屏蔽某一个位的信号

2.6 判断一个信号是否在集合中

sigismember(const sigset_t *set,int signum); 

2.7 设定对信号集内的信号的处理方式(阻塞或不阻塞)

#include <signal.h>
int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );

参数说明:

  • how:表示如何修改信号屏蔽字的标志,可取以下值:
    • SIG_BLOCK:将set中指定的信号添加到当前信号屏蔽字中。
    • SIG_UNBLOCK:将set中指定的信号从当前信号屏蔽字中移除。
    • SIG_SETMASK:用set中指定的信号集替换当前信号屏蔽字。
  • set:指向要修改的新的信号屏蔽字的指针。如果为NULL,则不会修改信号屏蔽字。
  • oset:用于保存旧的信号屏蔽字的指针。如果为NULL,则不会保存旧的信号屏蔽字。

函数返回值:

  • 成功:返回0,并将旧的信号屏蔽字保存到oset中(如果oset不为NULL)。
  • 失败:返回-1,并设置errno来指示错误的原因。

该函数用于在多线程编程、信号处理等场景中控制信号的屏蔽,以保证信号处理的正确性和可靠性。

示例:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void handle(int sig){printf("I get sig=%d\n",sig);}int main(){struct sigaction act;act.sa_handler = handle;   //注册回调函数sigemptyset(&act.sa_mask); //清空信号集,代表接收所有信号act.sa_flags = 0;          //通过将其设置为0,表示不使用任何额外的标志位,即默认行为。sigaction(SIGINT,&act,NULL); //信号捕获sigset_t set;               //定义信号集sigemptyset(&set);          //清空信号集sigaddset(&set,SIGINT);     //SIGINT,屏蔽SIGINT信号sigprocmask(SIG_BLOCK,&set,NULL);  //ctrl+c的信号阻塞,接收不到sleep(5);sigprocmask(SIG_UNBLOCK,&set,NULL); //取消信号阻塞while(1){sleep(1);}}

执行效果 :

2.8  使进程挂起(暂停执行)直到收到一个信号

int pause(void);

进程一直阻塞,直到被信号中断,返回值:-1 并设置errno为EINTR

函数行为:

-1 如果信号的默认处理动作是终止进程,则进程终止,pause函数没有机会返回。

-2 如果信号的默认处理动作是忽略,进程继续处于挂起状态,pause函数不返回

-3 如果信号的处理动作是捕捉,则调用完信号处理函数之后,pause返回-1。

-4 pause收到的信号如果被屏蔽,那么pause就不能被唤醒 

示例:pause阻塞效果

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char * argv[])
{pause();printf("after pause\n");
}//运行后结果程序阻塞中,未打印after pause,按ctrl+c或ctrl+\结束
linux@linux:~/Desktop$ ./pause 

 示例:pause阻塞效果2

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void handle(int sig)
{printf("Handle:I get sig=%d\n",sig);
}int main(int argc, char * argv[])
{struct sigaction act;act.sa_handler = handle;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGINT,&act,NULL);pause();printf("after pause\n");
}//运行结果,未恢复至原处理函数的执行效果
linux@linux:~/Desktop$ ./pause 
^CHandle:I get sig=2
after pause
linux@linux:~/Desktop$

 示例:pause阻塞效果3 ,实现一个等待信号的任务

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void handle(int sig)
{printf("Handle:I get sig=%d\n",sig);
}void mytask()
{printf("mytask:start\n");sleep(3);printf("mytask:end\n");
}int main(int argc, char * argv[])
{struct sigaction act;act.sa_handler = handle;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGINT,&act,NULL);pause();while(1){mytask();   pause();   //每次等待信号到来再执行mytask}printf("After pause\n");
}  //运行结果
linux@linux:~/Desktop$ ./pause 
^CHandle:I get sig=2
mytask:start
mytask:end
^CHandle:I get sig=2
mytask:start
mytask:end
^CHandle:I get sig=2
mytask:start
mytask:end

使用kill 发送SIGHUP信号关闭 

  示例:pause阻塞效果4 ,实现一个等待多个信号的任务(SIGINT,SIGHUP)

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void handle(int sig)
{printf("Handle:I get sig=%d\n",sig);
}void mytask()
{printf("mytask:start\n");sleep(3);printf("mytask:end\n");
}int main(int argc, char * argv[])
{struct sigaction act;act.sa_handler = handle;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGINT,&act,NULL);sigaction(SIGHUP,&act,NULL);	pause();while(1){mytask();pause();}printf("After pause\n");
}

按ctrl+c,或者使用kill -1发送关闭信号都可以捕获信号处理任务。

 示例:使用 sigaddset,屏蔽多个信号

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void handle(int sig)
{printf("Handle:I get sig=%d\n",sig);
}void mytask()
{printf("mytask:start\n");sleep(3);printf("mytask:end\n");
}int main(int argc, char * argv[])
{struct sigaction act;act.sa_handler = handle;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGINT,&act,NULL);sigaction(SIGHUP,&act,NULL);sigset_t set;sigaddset(&set,SIGHUP);sigaddset(&set,SIGINT);	pause();while(1){sigprocmask(SIG_BLOCK,&set,NULL);mytask();sigprocmask(SIG_UNBLOCK,&set,NULL);pause();}printf("After pause\n");
}

执行效果,在任务过程中设置了信号屏蔽,此时按ctrl+c或者kill -1去发送信号,不会执行handle打印,直到任务结束后再开启接收信号,防止任务被打断

2.9 更改进程的信号屏蔽字,并等待一个特定的信号到来

设定对信号集内的信号屏蔽并恢复。

int sigsuspend(const sigset_t *sigmask);

功能:函数用于临时更改进程的信号屏蔽字,并等待一个特定的信号到来,然后恢复原有的信号屏蔽字。和 pause 函数不同的是,它可以临时更改进程的信号屏蔽字,以便等待某个特定信号。

参数:

sigmask:希望屏蔽的信号

示例:解决任务中的信号丢失问题,sigsuspend相当于sigprocmask+pause

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void handle(int sig)
{printf("Handle:I get sig=%d\n",sig);
}void mytask()
{printf("mytask:start\n");sleep(3);printf("mytask:end\n");
}int main(int argc, char * argv[])
{struct sigaction act;act.sa_handler = handle;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGINT,&act,NULL);sigaction(SIGHUP,&act,NULL);sigset_t set;sigaddset(&set,SIGHUP);sigaddset(&set,SIGINT);	sigset_t set2;                sigemptyset(&set2);         //接收所有信号pause();while(1){sigprocmask(SIG_BLOCK,&set,NULL);mytask();//sigprocmask(SIG_UNBLOCK,&set,NULL);//pause();sigsuspend(&set2);}printf("After pause\n");
}

运行结果

linux@linux:~/Desktop$ ./pause 
^CHandle:I get sig=2         //1次CTRL+C
mytask:start  
mytask:end
^CHandle:I get sig=2         //1次CTRL+C
mytask:start
mytask:end
^CHandle:I get sig=2         //1次CTRL+C
mytask:start
^Cmytask:end                 //任务中途的1次CTRL+C
Handle:I get sig=2           //也被获取到并执行了
mytask:start
mytask:end

相关文章:

lv5 嵌入式开发-10 信号机制(下)

目录 1 信号集、信号的阻塞 2 信号集操作函数 2.1 自定义信号集 2.2 清空信号集 2.3 全部置1 2.4 将一个信号添加到集合中 2.5 将一个信号从集合中移除 2.6 判断一个信号是否在集合中 2.7 设定对信号集内的信号的处理方式(阻塞或不阻塞) 2.8 使进程挂起&#xff08;…...

【postgresql】 ERROR: multiple assignments to same column “XXX“

Cause: org.postgresql.util.PSQLException: ERROR: multiple assignments to same column "XXX"; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: multiple assignments to same column "XXX"; 原因&#xff1a;or…...

一文读懂Llama 2(从原理到实战)

简介 Llama 2&#xff0c;是Meta AI正式发布的最新一代开源大模型。 Llama 2训练所用的token翻了一倍至2万亿&#xff0c;同时对于使用大模型最重要的上下文长度限制&#xff0c;Llama 2也翻了一倍。Llama 2包含了70亿、130亿和700亿参数的模型。Meta宣布将与微软Azure进行合…...

完整指南:如何使用 Node.js 复制文件

文件拷贝指的是将一个文件的数据复制到另一个文件中&#xff0c;使目标文件与源文件内容一致。Node.js 提供了文件系统模块 fs&#xff0c;通过该模块可以访问文件系统&#xff0c;实现文件操作&#xff0c;包括拷贝文件。 Node.js 中文件拷贝方法 在 Node.js 中&#xff0c;有…...

ElementUI - 主页面--动态树右侧内容管理

一.左侧动态树 1.定义组件 ①样式&数据处理 <template><el-menu class"el-menu-vertical-demo" background-color"#334157"text-color"#fff" active-text-color"#ffd04b" :collapse"collapsed" router :def…...

全国排名前三的直播公司无锋科技入驻天府蜂巢成都直播产业基地

最近&#xff0c;全国排名前三的直播公司——无锋科技&#xff0c;正式宣布入驻位于成都的天府蜂巢直播产业基地&#xff0c;这一消息引起了业内人士的高度关注。成都直播产业基地一直是中国直播产业的重要地标之一&#xff0c;其强大的技术和资源优势为众多直播公司提供了广阔…...

机器人中的数值优化|【五】BFGS算法非凸/非光滑处理

机器人中的数值优化|【五】BFGS算法的非凸/非光滑处理 往期内容回顾 机器人中的数值优化|【一】数值优化基础 机器人中的数值优化|【二】最速下降法&#xff0c;可行牛顿法的python实现&#xff0c;以Rosenbrock function为例 机器人中的数值优化|【三】无约束优化&#xff0…...

ESP32S3的MPU-6050组件移植教程

前言 &#xff08;1&#xff09;实习公司要搞ESP32BOX的驱动移植&#xff0c;所有资料自己找还是比较折磨人的现在我分享几个官方的组件移植资料&#xff1a; <1>Find the most exciting ESP-IDF components&#xff08;ESP32的官方组件都可以在里面查&#xff0c;按照他…...

excel筛选后求和

需要对excel先筛选&#xff0c;后对“完成数量”进行求和。初始表格如下&#xff1a; 一、选中表内任意单元格&#xff0c;按ctrlshiftL&#xff0c;开启筛选 二、根据“部门”筛选&#xff0c;比如选择“一班” 筛选完毕后&#xff0c;选中上图单元格&#xff0c;然后按alt后&…...

pyspark 检测任务输出目录是否空,避免读取报错

前言 在跑调度任务时候&#xff0c;有时候子任务需要依赖前置任务的输出&#xff0c;但类似读取 Parquet 或者 Orc 文件时&#xff0c;如果不判断目录是否为空&#xff0c;在输出为空时会报错&#xff0c;所以需要 check 一下&#xff0c;此外Hadoop通常在写入数据时会在目录中…...

「网页开发|前端开发|Vue」10 vuex模块化:将数据划分成不同modules分别管理

本文主要介绍如何使用vuex的modules将状态数据根据不同模块进行划分并分别管理以及如何使用mapGetters快速将状态管理中的数据导入成local变量。 文章目录 本系列前文传送门一、场景说明二、使用modules划分不同模块三、使用Getters获取状态管理数据Getter传参mapGetters 辅助…...

苹果CMS插件-苹果CMS全套插件免费

网站内容的生成和管理对于网站所有者和内容创作者来说是一个挑战。有一些强大的工具可以帮助您轻松地解决这些问题。苹果CMS插件自动采集插件、采集发布插件以及采集伪原创发布插件&#xff0c;是这些工具之一。它们不仅可以极大地节省您的时间和精力&#xff0c;还可以提高您网…...

域环境介绍

一、概述 内网也指局域网&#xff0c;指的是某个区域由多台计算机互连而成的计算机组&#xff0c;范围通常在数千米以内&#xff0c;在局域网中&#xff0c;可以实现文件管理&#xff0c;应用软件共享&#xff0c;打印机共享、工作组内的日程安排、电子邮件和传真通信服务等&a…...

地球同步静止轨道上的中国卫星

3万6千公里地球同步静止轨道上的中国控制的卫星&#xff08;包括香港属非国产平台卫星、外国属中国平台卫星&#xff09;&#xff0c;共80颗&#xff1b;截止到2023年8月3日&#xff0c;共有563颗在轨卫星。 号定位名称发射时间用途重量1141.1W中星1C(FH2C)2015.12.10DFH4平台…...

HAProxy代理TCP(使用HAProxy 为TiDB-Server 做负载均衡)

目录 一、使用HAProxy 为TiDB-Server 做负载均衡环境1、创建文件夹2、配置haproxy.cfg3、创建 docker-compose.yaml 文件haproxy.cfg 配置说明[参照官方文档](https://pingcap.com/docs-cn/v3.0/reference/best-practices/haproxy/ "参照官方文档") 一、使用HAProxy …...

全新自适应导航网模板 导航网系统源码 网址导航系统源码 网址目录网系统源码

高价值目录网导航网整站源码 | 2999元价值,最新版本源码下载推荐 1、导航网一键获取目标站SEO信息,7.5版本增加会员中心一键获取网站信息网站权重,增加小程序提交发布,全新自适应模板; 2、可设置游客提交、游客提交人工审核,会员免审提交,会员提交人工审核,VIP会员免…...

无人直播间

失败&#xff01;&#xff01; 采用 ffmpeg 技术进行推流 推流代码&#xff1a; 【需要将rtmp替换为你的推流地址】 ffmpeg -re -stream_loop -1 -i "rain.mp4" -c copy -f flv ""推流地址获取 以哔哩哔哩为例 点击下方链接 开播设置 - 个人中心 - …...

Linux 服务器防止 ssh 暴力密码登录破解之使用 fail2ban

前言&#xff0c;网络安全越来越重要&#xff0c;如何保证网站安全至关重要&#xff0c;在使用 Linux 服务器时&#xff0c;如果未设置有效安全登录屏障&#xff0c;每日将会有数百甚至数万次的密码暴力尝试登录&#xff0c;本篇章将介绍两种 Linux 登录安全防护 一&#xff1…...

第十四届蓝桥杯大赛软件赛决赛 C/C++ 大学 B 组 试题 D: 合并数列

[蓝桥杯 2023 国 B] 合并数列 【问题描述】 小明发现有很多方案可以把一个很大的正整数拆成若干正整数的和。他采取了其中两种方案&#xff0c;分别将他们列为两个数组 { a 1 , a 2 , ⋯ a n } \{a_1, a_2, \cdots a_n\} {a1​,a2​,⋯an​} 和 { b 1 , b 2 , ⋯ b m } \{b…...

ChatGPT必应联网功能正式上线

今日凌晨发现&#xff0c;ChatGPT又支持必应联网了&#xff01;虽然有人使用过newbing这个阉割版的联网GPT4&#xff0c;但官方版本确实更加便捷好用啊&#xff01; 尽管 ChatGPT 此前已经展现出了其他人工智能模型无可比拟的智能&#xff0c;但由于其训练数据的限制&#xff…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...