Linux —— 信号阻塞
目录
一,信号内核表示
sigset_t
sigprocmask
sigpending
二,捕捉信号
sigaction
三,可重入函数
四,volatile
五,SIGCHLD
信号常见概念
- 实际执行信号的处理动作,称为信号递达Delivery;
- 信号从产生到递达的状态,称为信号未决Pending;
- 进程可选择阻塞某个信号;
- 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才会执行递达动作;
- 阻塞和忽略是不同的,信号被阻塞就不会递达,忽略是递达后可选的一种处理动作;
一,信号内核表示
- 每个信号都有两个标志:阻塞、未决,及一个函数指针表示的动作;信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志;
- SIGHUP信号,未产生也未阻塞,如递达时将执行默认动作;
- SIGINT信号,产生过但被阻塞,暂时不能递达,处理动作为忽略;
- SIGQUIT信号,未产生,如产生将被阻塞,处理动作为用户自定义函数;如该信号在阻塞前产生多次,POSIX允许系统递送该信号一次或多次,Linux常规信号在递达前产生多次只计一次,而实时信号在递达前产生多次可依次放在一个队列内;
sigset_t
- 每个信号只有一个bit的未决标志,0或1,不记录该信号产生的次数;阻塞标志也是如此;
- 未决和阻塞标志可用相同的数据类型sigset_t来存储,sigset_t称为信号集;该类型可表示每个信号的有效或无效;
//信号集操作函数
//在使用sigset_t类型的变量之前,一定要调用sigempty或sigfillset初始化,以使信号集处于确定状态;
//初始化后,即可调用sigaddset和sigdelset在信号集中添加或删除某种有效信号;
#include <signal.h>
int sigemptyset(sigset_t* set) //初始化信号集,使所有信号对应bit清零,表示该信号集不包含任何有效信号;
int sigfillset(sigset_t* set) //初始化信号集,使所有信号对应bit清零,表示该信号集的有效信号;
int sigaddset(sigset_t* set, int signo)
int sigdelset(sigset_t* set, int signo)
int sigismember(const sigset_t* set, int signo)
sigprocmask
- 此函数可读取或更改进程的信号屏蔽字(阻塞信号集);
#include <signal.h>
int sigprocmask(int how, const sigset_t* set, sigset_t* oset);
- 如oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出;
- 如set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改;
- 如oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset,然后根据set和how更改信号屏蔽字;
- 如当前信号屏蔽字为mask,则下表说明了how参数的可选值;
- 如调用此函数解除了对当前若干个未决信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达;
sigpending
- 检测未决信号;
#include <signal.h>
int sigpending(sigset_t* set)
#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std; void show_pending(sigset_t* pending){ for(int i=1; i<32; i++){ if(sigismember(pending, i)) cout<<"1"; else cout<<"0"; } cout<<endl;
} int main()
{ sigset_t in, out; sigemptyset(&in); sigemptyset(&out); sigaddset(&in, 2); sigprocmask(SIG_SETMASK, &in, &out); int count=0; sigset_t pending; while(1){ sigpending(&pending); show_pending(&pending); sleep(1); if(count==10){ sigprocmask(SIG_SETMASK, &out, &in); //恢复2号信号后, 2信号立即递达并执行默认操作 cout<<"my: "; show_pending(&in); cout<<"recover default: "; show_pending(&out); } count++; } return 0;
}
[wz@192 Desktop]$ g++ test.cpp -o test
[wz@192 Desktop]$ ./test
0000000000000000000000000000000
0000000000000000000000000000000
0000000000000000000000000000000
^C0100000000000000000000000000000
0100000000000000000000000000000
0100000000000000000000000000000
0100000000000000000000000000000
0100000000000000000000000000000
0100000000000000000000000000000
0100000000000000000000000000000
0100000000000000000000000000000
二,捕捉信号
如信号的处理动作是用户自定义函数,在信号递达时就调用该函数,称为捕捉信号;由于信号处理函数的代码在用户空间,处理过程比较复杂;如,用户程序注册了SIGQUIT信号的处理函数sighandler,当前正在执行main函数,此时发生中断或异常,切换达到内核态;在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT递达;内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函数,sighandler和main函数使用不同的堆栈空间,不存在调用和被调用的关系,是两个独立的控制流程;sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态;如没有新的信号递达,再返回用户态就是恢复main函数的上下文继续执行;
sigaction
当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来的信号屏蔽字,这样就保证了在处理某个信号时,如这种信号再次产生,那么会被阻塞到当前处理结束为止;
如在调用信号处理函数时,除了当前信号被自动屏蔽之外,还希望自动屏蔽另外一些信号,则用sa_mask字段说明这些需要额外屏蔽的信号,当信号处理函数返回时自动恢复原来的信号屏蔽字;
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
using namespace std;void handler(int signo){cout<<"get a signo: "<<signo<<endl;exit(10);
}int main(){struct sigaction act, oact;act.sa_handler = handler;act.sa_flags = 0;sigemptyset(&act.sa_mask);//act.sa_restorer = nullptr;//act.sa_sigaction = nullptr;sigaction(SIGINT, &act, &oact);while(1){cout<<"running..."<<endl;sleep(1);}return 0;
}
用户态,内核态;用户态需通过系统调用来访问内核数据,调用系统调用时系统会自动切换 身份;CPU会存在一个权限相关的寄存器数据,标识所处状态;每个用户进程都有自己的用户级页表,而OS只有一份内核页表;由于用户态和内核态的权限级别不同,所能看到的资源也是不一样的;
实时信号,不会丢失,会排队执行;
三,可重入函数
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
using namespace std;void show(int signo){int i=0;while(i<5){cout<<"show(), signo: "<<signo<<endl;i++;sleep(1);}
}void handler(int signo){cout<<"handler calling..."<<endl;show(signo);
}int main(){struct sigaction act, oact;act.sa_handler = handler;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGINT, &act, &oact);show(999);return 0;
}
[wz@192 Desktop]$ ./test
show(), signo: 999
show(), signo: 999
show(), signo: 999
^Chandler calling...
show(), signo: 2
show(), signo: 2
show(), signo: 2
show(), signo: 2
show(), signo: 2
show(), signo: 999
show(), signo: 999
像以上,insert插入函数被不同控制流调用,可能在第一次调用还没返回时,就再次进入该函数,称为重入;insert函数访问一个全局链表,有可能因为插入而造成错乱,像这样的函数称为不可重入函数;反之,如一函数只访问自己的局部变量或参数,称为可重入函数;所学的大部分函数都是不可重入的;
如函数符合以下条件之一,则是不可重入:
- 调用了malloc或free,因malloc也是也是用全局链表来管理堆的;
- 调用了标准I/O函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构;
四,volatile
C语言关键字,保持内存的可见性;
#include <stdio.h>
#include <signal.h>int flag=0;
void handler(int signo){flag=1;printf("handler calling, get signo: %d\n", signo);
}int main(){signal(2, handler);while(!flag); //注意没有循环体printf("process quit normal!\n");return 0;
}
[wz@192 Desktop]$ gcc -o test test.c
[wz@192 Desktop]$ ./test
^Chandler calling, get signo: 2
process quit normal!
//优化级别1
[wz@192 Desktop]$ gcc -o test test.c -O1
[wz@192 Desktop]$ ./test
^Chandler calling, get signo: 2
^Chandler calling, get signo: 2
^Chandler calling, get signo: 2
优化后,flag被放在了CPU的寄存器当中,while循环的flag并不是内存中的最新flag;使用volatile关键字修饰变量后,则该变量不允许在被优化,对该该变量的任何操作都必须在真实的内存中进行;
#include <stdio.h>
#include <signal.h>volatile int flag=0;
void handler(int signo){flag=1;printf("handler calling, get signo: %d\n", signo);
}int main(){signal(2, handler);while(!flag); //注意没有循环体printf("process quit normal!\n");return 0;
}
[wz@192 Desktop]$ gcc -o test test.c -O1
[wz@192 Desktop]$ ./test
^Chandler calling, get signo: 2
process quit normal!
五,SIGCHLD
SIGCHLD是第17号信号;进程wait、waitpid函数清理僵死进程,父进程可阻塞等待子进程结束,也可非阻塞查询是否有子进程结束等待清理(轮询);第一种方式父进程阻塞了,就不能处理自己的工作,第二种方式父进程在处理自己的工作同时还要记得轮询,程序实现复杂;
其实,子进程在终止时会给父进程发送SIGCHLD信号,该信号默认处理动作为忽略,父进程可自定义SIGCHLD信号的处理函数;这样父进程只需专心处理自己的工作,不必关心子进程;子进程终止时通知父进程,父进程在信号处理函数中调用wait清理子进程即可;
由于UNIX的历史原因,要想不产生僵死进程,还可在父进程调用sigaction时将SIGCHLD处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理,不会产生僵死进程,也不会通知父进程;系统默认的忽略动作和用户用sigaction函数自定义的忽略,通常是没有区别的,但这是特例;此方法对于Linux可用,但不保证在其他UNIX系统上都可使用;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>void handler(int signo){printf("father get signo: %d\n", signo);pid_t id;//可能有多个子进程while((id=waitpid(-1,NULL,WNOHANG))>0){printf("wait child success: %d\n", id);}printf("child is quit! %d\n", getpid());
}int main(){signal(SIGCHLD, handler);pid_t cid;if((cid=fork()) == 0){printf("child: %d\n", getpid());sleep(3);exit(1);}while(1){printf("father process...!\n");sleep(1); //可以提前被唤醒}return 0;
}
[wz@192 Desktop]$ gcc -o test test.c
[wz@192 Desktop]$ ./test
father process...!
child: 99919
father process...!
father process...!
father get signo: 17
wait child success: 99919
child is quit! 99918
father process...!
father process...!
father process...!
father process...!
如不设置signal,子进程终止时,就会产生僵死进程;
如设置为SIG_IGN,子进程终止时,自动清理;
//如设置为忽略,fork出来的子进程在终止时会自动清理,不会产生僵死进程 signal(SIGCHLD, SIG_IGN);
等待子进程,避免Z进程内存泄露,可能需获取子进程的退出码;父进程不关心子进程退出码,可不wait,如关心退出码必须wait;
相关文章:
Linux —— 信号阻塞
目录 一,信号内核表示 sigset_t sigprocmask sigpending 二,捕捉信号 sigaction 三,可重入函数 四,volatile 五,SIGCHLD 信号常见概念 实际执行信号的处理动作,称为信号递达Delivery;信…...
【【萌新编写riscV之计算机体系结构之CPU 总二】】
萌新编写riscV之计算机体系结构之CPU 总二(我水平太差总结不到位) 在学习完软件是如何使用之后 我们接下来要面对的问题是 整个程序是如何运转的这一基本逻辑 中央处理器(central processing unit,CPU)的任务就是负责提取程序指令࿰…...
error:03000086:digital envelope routines::initialization error
项目背景 前端vue项目启动突然报错error:03000086:digital envelope routines::initialization error 我用的开发工具是vscode,node版本是v18.17.0 前端项目版本如下↓ 具体报错如下↓ 报错原因 node版本过高 解决方法 1输入命令 $env:NODE_OPTIONS"--op…...
暴涨130万粉仅用3个月,一招转型成B站热门UP主
- 导语 起号难、找不到内容方向、没流量、没粉丝等等运营困境环绕在创作者之间,近期,有黑马UP主短时间内就在B站涨粉百万,飞升成为热门UP主,以下,飞瓜数据(B站版)剖析黑马UP主运营技巧…...
【Linus】vim的使用:命令模式、底行模式、插入模式、视图模式、替换模式的常用操作介绍
目录 注意:以下操作前提是要确保你输入法是英文模式 一、进入和退出各个模式的方法 1.命令模式 2.底行模式 3.插入模式 4.视图模式 5.替换模式 二、在命令模式中一些常用的操作 1.移动光标 2.删除文字 3.复制 4.替换 5.撤销上一次操作 6.更改 7.跳至指…...
leetcode第362场周赛补题
8029. 与车相交的点 - 力扣(LeetCode) 思路:差分数组 class Solution { public:int numberOfPoints(vector<vector<int>>& nums) {int diff[102] {}; for(auto p : nums)//差分{diff[p[0]] ;diff[p[1] 1] -- ;}int res …...
SpringMvc 之crud增删改查应用
目录 1.创建项目 2.配置文件 2.1pom.xml文件 2.2 web.xml文件 2.3 spring-context.xml 2.4 spring-mvc.xml 2.5 spring-MyBatis.xml 2.6 jdbc.properties 数据库 2.7 generatorConfig.xml 2.8 日志文件log4j2 3.后台代码 3.1 pageBean.java 3.2切面类 3.3 biz层…...
【业务功能109】微服务-springcloud-springboot-Skywalking-链路追踪-监控
Skywalking skywalking是一个apm系统,包含监控,追踪,并拥有故障诊断能力的 分布式系统 一、Skywalking介绍 1.什么是SkyWalking Skywalking是由国内开源爱好者吴晟开源并提交到Apache孵化器的产品,它同时吸收了Zipkin /Pinpoint …...
《向量数据库指南》——AI原生向量数据库Milvus Cloud 2.3架构升级
架构升级 GPU 支持 早在 Milvus 1.x 版本,我们就曾经支持过 GPU,但在 2.x 版本中由于切换成了分布式架构,同时出于对于成本方面的考虑,暂时未加入 GPU 支持。在 Milvus 2.0 发布后的一年多时间里,Milvus 社区对 GPU 的呼声越来越高,再加上 NVIDIA 工程师的大力配合——为…...
Flutter中实现交互式Webview的方法
前言: Flutter是一款强大的跨平台移动应用开发框架,而Webview则是在应用中展示Web内容的重要组件。本文将介绍如何在Flutter应用中实现交互式的Webview,以便为用户提供更加丰富的内容和功能。 1. 引入webview_flutter插件 要在Flutter应用中…...
【Java Web】用Redis优化登陆模块
使用Redis存储验证码 验证码需要频繁访问和封信,对性能要求高;验证码不需要永久保存,通常在很短时间内失效;分布式部署,存在Session共享问题; 使用Redis存储登陆凭证 处理每次请求时,都要查询用…...
华为云云耀云服务器L实例评测|docker私有仓库部署手册
【软件安装版本】【集群安装(是)(否)】 版本号 文档编写 文档审核 创建日期 修改日期 1.0 jzg jzg 2023.9.13 一. 部署规划与架构 1. 规划:(集群:网络规划&…...
JAVA-3DES对称加解密工具(不依赖第三方库)
import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;public class EncryptUtil {// 密钥public static final String ENCR…...
基于Matlab卡尔曼滤波的IMU和GPS组合导航数据融合(附上源码+数据)
本文介绍了如何使用Matlab实现惯性测量单元(IMU)和全球定位系统(GPS)组合导航数据融合的卡尔曼滤波算法。通过将IMU和GPS的测量数据进行融合,可以提高导航系统的精度和鲁棒性。我们将详细介绍卡尔曼滤波的原理和实现步…...
net自动排课系统完整源码(适合智慧校园)
目录 1 net自动排课系统完整源码(适合智慧校园) 1.1 后台管理admin 1.1.1 菜单 1.1.2 教学计划 net自动排课系统完整源码(适合智慧校园) 后台管理admin<%@ Page Language="C#" AutoEventWireup="true" CodeBehind=&...
Matlab匿名函数教程
Matlab匿名函数是一种方便、简洁的函数定义方式,可以在不使用函数文件的情况下,直接在命令行或脚本中定义函数。本文将介绍Matlab匿名函数的基本语法和用法。 匿名函数的基本语法如下: function_handle (input_variables) expression其中&…...
【Vue】一文让你进入Vue的大门
Vue简介 官网 ● 英文官网 ● 中文官网 介绍与描述 Vue历史 Vue 是一套用来动态构建用户界面的渐进式JS框架 构建用户界面:把数据通过某种办法变成用户界面 渐进式:Vue可以自底向上逐层的应用,简单应用只需要一个轻量小巧的核心库,…...
Linux mmap读/写触发共享文件页生命周期
概述 Linux的mm内存子系统的核心功能就要要管理各种类型的page,确保能高效分配和释放,让物理内存得以最大化使用。初识内存系统往往关注的是page的申请和管理流程,容易忽略page的释放回收流程,其实理解mm中的内存回收和释放也是最核心的机制。 Linux内核为了支持各种场景…...
linux 用户、组操作
一、创建用户并设置密码 #创建用户 duoergun useradd duoergun #设置用户 duoergun 密码 passwd duoergun二、创建组 #创建组 qingdynasty groupadd qingdynasty三、用户添加到组,用户从组删除 #添加用户duoergun到组qingdynasty usermod -aG qingdynasty duoer…...
MySQL报错this is incompatible withsal mode=only full group by处理办法
问题说明 报这个错误是指,在查询分组时展示了非分组字段。举例: select id , user_name from user group by user_name;上述语句查询id和user_name字段,其中user_name进行了分组,id并没有分组,这时候mysql就会报上述…...
Mybatis 动态语言 - mybatis-freemarker
前面我们介绍了Mybatis动态SQL的使用;本篇我们介绍使用mybatis- freemarker动态语言生成动态SQL。 如果您对Mybatis动态SQL不太了解,建议您先进行了解后再阅读本篇,可以参考: Mybatis 动态SQL – 使用if,where标签动态生成条件语…...
软件源码开发,网络中的“摄像头”:运维监控系统
在日常生活中,我们不管是在大街小巷,还是在商场大厦都可以见到一个圆形或是方形带有镜片的“小盒子”,这个“小盒子”就是摄像头,摄像头作为一个能实时录制记录它能照到范围内的视频图像的工具,可以在丢失物品、抓捕坏…...
ping命令
打开运行窗口 首先,我们需要打开运行窗口,可以通过按下WinR组合键打开。然后,在窗口中输入cmd,进入dos命令。 在命令行中输入ping命令 在dos命令行中,我们可以通过输入ping命令来检测网络连接。例如,我们…...
MFC:程序的托盘显示
介绍 关键技术,API函数Shell_NotifyIcon,具体查看msdn吧 实现的主要代码 #define MY_TRAY_ICON_ID (1)/ //其他代码:略BEGIN_MESSAGE_MAP(CTestShowTrayDlg, CDialogEx)//...ON_MESSAGE(WM_MY_TRAY_ICON, &CTestShowTrayDlg::OnMessag…...
AI绘画:StableDiffusion实操教程-斗破苍穹-云韵-婚服(附高清图下载)
大家好,我是小梦,最近一直研究AI绘画。 不久前,我与大家分享了StableDiffusion的全面教程:“AI绘画:Stable Diffusion 终极宝典:从入门到精通 ” 然而,仍有些读者提出,虽然他们已经…...
JS装饰器的介绍
装饰器的基本介绍 装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,访问符,属性或参数上。 装饰器使用expression这种形式,expression求值后必须为一个函数,它会在运行时被调用,被装饰的…...
微信小程序(原生)使用Swiper实现(商品详情)视频和图片轮播(仿京东/淘宝商品详情头部视频+图片轮播)
一、需求 1、如果第一是视频,不进行自动轮播 2、可以手动滑动切换 3、点击播放视频,也可以手动滑动切换 4、视频播放完后,自动轮播 5、视频可以点击暂停和全屏播放二、最终效果 三、源码 播放icon使用了TDesign组件库 1、wxml <swiper c…...
关于for in 循环会遍历原型链上的属性的问题
关于for in 循环会遍历原型链上的属性的问题 for in可遍历原型链上扩展的属性,Object.keys() 只遍历自身属性 1.使用 for in 循环遍历对象的属性时,原型链上的所有属性都将被访问: Object.prototype.say"cgl"; // 修改Object.p…...
冠达管理:人民币升值板块个股?
人民币增值是当前热门的论题之一。面对这一趋势,许多投资者开端重视人民币增值板块个股的投资时机。可是,终究哪些职业和个股能够从人民币增值中获益?下面从多个视点分析这个问题。 一、出口相关职业 跟着人民币增值,我国的出口企…...
27.EI文章复现《高比例清洁能源接入下计及需求响应的配电网重构》
下载地址:高比例清洁能源接入下计及需求响应的配电网重构 1主要内容 该程序复现《高比例清洁能源接入下计及需求响应的配电网重构》,以考虑网损成本、弃风弃光成本和开关操作惩罚成本的综合成本最小为目标,针对配电网重构模型的非凸性&…...
免费空间asp网站/腾讯广告代理商加盟
C#導出Excel方法有多種﹐常用的按照Microsoft 的方法如下: 1﹑"Use Automation to Transfer Data Cell by Cell " 2﹑"Use Automation to Transfer an Array of Data to a Range on a Worksheet " 3﹑"Use Automation to Transfer an ADO Recordset t…...
西安市网站搭建/新闻头条今日要闻军事
STM32F407 FreeRTOS移植 一、获取FreeRTOS源码 打开FreeRTOS官网:www.freertos.org,在官网下载即可,这里不做步骤说明,或者通过百度下载即可,下载网址: 链接:https://pan.baidu.com/s/1l3QMTd…...
要强化人大网站建设/北京高端网站建设
English Learning - L2 语音作业打卡 前元音 [i:] Day7 2023.2.27 周一💌 发音小贴士:💌 当日目标音发音规则/技巧:🍭 Part 1【热身练习】🍭 Part2【练习内容】🍭【练习感受】🍓元音…...
网站常用布局/电脑培训零基础培训班
很荣幸今天有这个机会跟大家分享我自己对人工智能伦理的一些观察和思考。我今天分享的主题是“人工智能伦理:问题与策略”。 1.1人工智能时代正在加速到来,算法决策开始兴起 我们看到,第三次AI浪潮已经开启,这体现在三个层面。 在…...
北京北站/品牌广告
WordCountmap类import java.io.IOException;import org.apache.hadoop.io.IntWritable;import org.apache.hadoop.io.LongWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapreduce.Mapper;/*** mapper* 负责从文件中一行一行读取单词 并根据给定的分隔符…...
企业网站排名靠前/seo站内优化最主要的是什么
我在研究互联网上的AES加密时发现了以下代码。 在这段代码中,我发现key和iv是使用hash function生成的,并使用sha256 。 我想知道这种方法对于使用PHP加密文本是否安全。我在网上找到的代码如下,<?php function encrypt_decrypt($action,…...