Linux 进程间的信号

1.信号的初认识

        信号是进程之间事件异步通知的一种方式,属于软中断。通俗来说信号就是让用户或进程给其他用户和进程发生异步信息的一种方式。对于信号我们可以根据实际生活,对他有以下几点认识:1.在没有产生信号时我们就知道产生信号要怎么处理(如古代时边境产生烽火,就要集结军队)。2.当信号产生时如果进程在忙着其他工作,信号需要保存,合适时候再处理。3.信号的产生是随机的,我们无法预测,所以信号是异步发生的。我们根据生活中的信号,可以对进程中的信号做出以上认识,下面我们来深入学习Linux信号.

2.信号的产生

1.kill命令产生信号

输入kill -l,我们可以查看操作系统中的各种信号,1-31为非实时信号,32-64为实时信号。

kill 命令后接-数字对应的信号再接进程pid,就可以对指定的进程发生指定的信号。如kill -9 2276702就可以对2276702号进程发送9号信号。

2. 通过终端按键产生信号

        如我们在进程运行的过程中,按下ctrl + c:向当前进程发送2号信号。 ctrl + :向当前进程发送3号信号。 ctrl + z:向当前进程发送20号信号等,我们可以通过键盘来发信号。

3.硬件异常产生信号

        硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除 以0的指令,CPU的运算单元会产生异常,内核将这个异常解释 为SIGFPE信号发送给进程。再比如当前进程访问了非 法内存地址,,MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给进程。

4.由软件条件产生信号

如管道在写端打开,读端关闭时会产生13号信号给进程,由软件条件也会产生信号。

2.信号的保存及阻塞

1.相关概念:

  • 实际执行信号的处理动作称为信号递达(Delivery)
  • 信号从产生到递达之间的状态,称为信号未决(Pending)。
  • 进程可以选择阻塞 (Block )某个信号。
  • 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作.
  • 注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

2.实现原理

 task_struct 的某个指针指向三张位图block(阻塞),pending(未绝),handler(处理),其中位图中下标数字+1表示几号信号。在block位图中元素为0代表不阻塞信号,为1则要阻塞,如上图block就表示要阻塞2号信号和3号信号。pending也类似,0表示没有信号需处理,1表示有信号需处理,如上图就表示1号信号需处理。hander位图则存入对应的处理方法指针,表示对应信号的处理动作。

从上图来看,pending中每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。 因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号 的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有 效”和“无效”的含义是该信号是否处于未决状态

3.对pending,block位图操作

1.信号集操作函数
#include <signal.h>
int sigemptyset(sigset_t *set);//对信号集全置0
int sigfillset(sigset_t *set);//对信号集全置1
int sigaddset (sigset_t *set, int signo);//将信号集指定的signal信号位置1
int sigdelset(sigset_t *set, int signo);//将信号集指定的signal信号位置0
int sigismember(const sigset_t *set, int signo);//判断信号是否在信号集中为1

     这四个函数都是成功返回0,出错返回-1。

2.sigprocmask函数

调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 
返回值:若成功则为0,若出错则为-1 

oset为输出型参数,读取进程的当前信号屏蔽字通过oset参数传出进行保存。set是输入型参数,按照set更改进程的信号屏蔽字。参数how指示如何更改。下图是how的可选值及作用:

3.sigpending函数

读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1。 

#include <signal.h>
int sigpending(sigset_t *set);
4.代码讲解 

这里我们模拟一种情况来使用上面的函数,加深理解。我们先屏蔽2号信号,打印pending位图,然后输入2号信号,20秒后再解除2号的屏蔽再输入2号信号,代码如下

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cassert>
#include <sys/wait.h>void PrintSig(sigset_t &pending)
{std::cout << "Pending bitmap: ";for (int signo = 31; signo > 0; signo--){if (sigismember(&pending, signo)){std::cout << "1";}else{std::cout << "0";}}std::cout << std::endl;
}
int main()
{// 1. 屏蔽2号信号sigset_t block, oblock;sigemptyset(&block);//全置零sigemptyset(&oblock);//全置零sigaddset(&block, 2); //此时只是对block变量进行修改没有设置进当前进程的PCB block位图中int n = sigprocmask(SIG_SETMASK, &block, &oblock);//将block变量置进当前进程的PCB block位图中std::cout << "block 2 signal success" << std::endl;std::cout << "pid: " << getpid() << std::endl;int cnt = 0;while (true){// 2. 获取进程的pending位图sigset_t pending;sigemptyset(&pending);n = sigpending(&pending);// 3. 打印pending位图中的收到的信号PrintSig(pending);cnt++;// 4.20秒后解除对2号信号的屏蔽if (cnt == 20){std::cout << "解除对2号信号的屏蔽" << std::endl;n = sigprocmask(SIG_UNBLOCK, &block, &oblock); // 2号信号会被立即递达, 默认处理是终止进程assert(n == 0);}// 我还想看到pending 2号信号 1->0 : 递达二号信号!sleep(1);}return 0;
}

运行结果: 

当我们屏蔽2号信号再输入2号信号时, 进程不能处理2号信号,放入pending位图中等候,解除屏蔽时2号信号可以处理,进程处理2号信号退出。

4.捕捉信号

1.什么时候处理信号

进程地址空间中存在用户空间(用户进程使用的内存资源)和内核空间(操作系统使用的内存资源),用户进程默认处于用户态,此时进程无法以任何形式访问操作系统的资源。当进程因系统调用,中断,异常或重新分配到时间片陷入内核态。

2.处理信号动作自定义的信号流程

当处理信号动作自定义的信号时,由于信号处理函数在用户态,为了不影响内核必须返回用户态。处理完后再返回内核执行完流程。简略图如下:

3.信号捕捉函数sigaction 
#include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact); 

 sigaction函数可以读取和修改与指定信号相关联的处理动作。调用成功则返回0,出错则返回- 1。signo 是指定信号的编号。若act指针非空,则根据act修改该信号的处理动作。若oact指针非 空,则通过oact传 出该信号原来的处理动作。act和oact指向sigaction结构体:

其中第一个成员变量是函数指针,用于执行自定义动作,第三个变量表示我们需要添加的屏蔽信号,第四个置为0,其他我们暂时不讲解。

将sa_handler赋值为常数SIG_IGN传给sigaction表示忽略信号,赋值为常数SIG_DFL表示执行系统默认动作。该函数返回 值为void,可以带一个int参数,通过参数可以得知当前信号的编号,这样就可以用同一个函数处理多种信号。显然,这也是一个回调函数,不是被main函数调用,而是被系统所调用。

需要注意的是当某个信号处理函数被调用时,系统自动将当前信号加入信号屏蔽字,等信号处理函数调用完毕后再移除,这样是为了防止信号嵌套式进行捕捉处理。

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

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

相关文章

LLM - 卷积神经网络(CNN)

1. 卷积神经网络结构&#xff1a;分为输入层&#xff0c;卷积层&#xff0c;池化层&#xff0c;全连接层&#xff1b; &#xff08;1&#xff09;首先进入输入层&#xff0c;对数据数据进行处理&#xff0c;将输入数据向量化处理&#xff0c;最终形成输入矩阵。 &#xff08;…

电脑录歌用什么软件好?分享电脑录音软件:6款

短视频普遍的今天&#xff0c;越来越多的人喜欢通过电脑进行音乐创作和录制。然而&#xff0c;面对市面上琳琅满目的电脑录音软件&#xff0c;很多人可能会感到困惑&#xff1a;电脑录歌用什么软件好呢&#xff1f;本文将为大家分享六款精选的录音软件&#xff0c;帮助大家找到…

校园电动车安全监控和调度系统-计算机毕业设计源码13028

摘要 校园电动车安全监控和调度系统是为了确保校园内电动车的安全和高效运行而设计的。该系统通过安装在电动车上的监控设备&#xff0c;实时监测电动车的运行状态&#xff0c;包括速度、位置、电池电量等&#xff0c;一旦发现异常情况&#xff0c;系统会立即发出警报并通知相关…

【matlab】分类回归——智能优化算法优化径向基神经网络

径向基&#xff08;Radial Basis Function, RBF&#xff09;神经网络 一、基本概念 径向基函数&#xff08;RBF&#xff09;&#xff1a;是一个取值仅仅依赖于离原点&#xff08;或某一中心点&#xff09;距离的实值函数。在RBF神经网络中&#xff0c;最常用的径向基函数是高…

使用patch-package自动修改node_modules中的内容/打补丁

背景 在使用VuePress搭建个人博客的过程中&#xff0c;我需要使用到一个用来复制代码块的插件uepress-plugin-nuggets-style-copy。 问题&#xff1a;插件可以正常安装&#xff0c;但是启动会报错。通过查看错误信息&#xff0c;定位是插件中的copy.vue文件出现错误&#xff0c…

将循环转化为递归的三种方法,求1+2+3……+n等差数列

解法一&#xff1a;使用公共变量s&#xff0c;递归循环1~n加到s上 #include<bits/stdc.h> using namespace std; int n,s; void fun(int i){if(i<n){ssi;fun(i1);}}int main(){cin>>n;fun(1);cout<<s;return 0; } 解法二&#xff1a;通过层层累加&#x…

C语言自定义类型——联合体、枚举

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、联合体&#xff08;一&#xff09;、联合体的声明&#xff08;二&#xff09;、联合体的特点&#xff08;三&#xff09;、联合体大小的计算&#xff01;&a…

二维树状数组区域查询

落谷4514 过关代码如下 #define _CRT_SECURE_NO_WARNINGS #include<bits/stdc.h> using namespace std; //#define int long longconst int N 2050; int t1[N][N], t2[N][N], t3[N][N], t4[N][N]; int lowbit(int x) { return x & (-x); } int n, m; void update(…

Mybatis实现RBAC权限模型查询

RBAC权限模型 Role-Based Access Control&#xff0c;中文意思是&#xff1a;基于角色&#xff08;Role&#xff09;的访问控制。这是一种广泛应用于计算机系统和网络安全领域的访问控制模型。 简单来说&#xff0c;就是通过将权限分配给➡角色&#xff0c;再将角色分配给➡用…

应急响应-网站入侵篡改指南Webshell内存马查杀漏洞排查时间分析

查看146天的内存马 方法&#xff1a; 1. 日志 这种地址一般在扫描 还要注意post传参注入 对其进行全局定位 发现有sql注入 我们可以也尝试去sqlmap注入 如果以这种方式注入ua头就会改变 2. 了解自己的中间件&#xff0c;框架&#xff0c;cve&#xff0c;等 因为不知道时间…

Unity中TimeLine的一些用法

Unity中TimeLine的一些用法 概念其他 概念 无Track模式&#xff08;PlayableAsset、PlayableBehaviour&#xff09; 1. 两者关系 运行在PlayableTrack中作用 PlayableBehaviour 实际执行的脚本字段并不会显示在timeline面板上 PlayableAsset PlayableBehaviour的包装器&#x…

[AI Perplexica] 安装指南:轻松部署AI驱动的开源搜索引擎

[AI Perplexica] AI驱动的开源搜索引擎[AI Perplexica] 深入解析&#xff0c;AI 架构揭秘 之前&#xff0c;我们看过了 Perplexica 的介绍&#xff0c;特点和架构&#xff0c;了解了其工作原理。 今天&#xff0c;我们一起来部署下 安装 docker 安装 docker https://docs.…

设计模式探索:代理模式

1. 什么是代理模式 定义 代理模式是一种结构型设计模式&#xff0c;通过为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和实际对象之间起到中介作用&#xff0c;可以在不改变真实对象的情况下增强或控制对真实对象的访问。 目的 代理模式的主要目的是隐…

【IT领域新生必看】Java编程中的神奇对比:深入理解`equals`与`==`的区别

文章目录 引言什么是操作符&#xff1f;基本数据类型的比较示例&#xff1a; 引用类型的比较示例&#xff1a; 什么是equals方法&#xff1f;equals方法的默认实现示例&#xff1a; 重写equals方法示例&#xff1a; equals与的区别比较内容不同示例&#xff1a; 使用场景不同示…

伯克利、斯坦福和CMU面向具身智能端到端操作联合发布开源通用机器人Policy,可支持多种机器人执行多种任务

不同于LLM或者MLLM那样用于上百亿甚至上千亿参数量的大模型&#xff0c;具身智能端到端大模型并不追求参数规模上的大&#xff0c;而是指其能吸收大量的数据&#xff0c;执行多种任务&#xff0c;并能具备一定的泛化能力&#xff0c;如笔者前博客里的RT1。目前该领域一个前沿工…

linux19:程序替换

一&#xff1a;最简单的看看程序替换是什么样的&#xff08;单个进程版&#xff09; 1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 int main()5 {6 printf("Before : I am a process , myPid:%d,myPPid:%d\n",getpid(),getpp…

Java项目:基于SSM框架实现的德云社票务管理系统【ssm+B/S架构+源码+数据库+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的德云社票务管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功…

windows下搭建python+jupyter notebook

一.下载python 下面网址下载python3 https://www.python.org/ 二. 安装jupyter notebook 三. 修改配置 四. 检测是否正常运行

华为OD机试 - 跳马 - 广度优先搜索BFS(Java 2024 D卷 200分)

华为OD机试 2024D卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测…

windows 7 安装IPP协议,支持Internet打印

1 windows 7 安装IPP协议,支持Internet打印 #控制面板--打开或关闭Windows功能 3 复制Printers 文件夹 到 c:\inetpub\wwwroot\,复制msw3prt.dll到c:\windows\system32\ 4 打开IIs管理器 #报错:模块列表中不存在此处理程序所需的指定模块。如果您添加脚本映射处理程序映射&…