linux---信号的捕捉和处理



提示:以下是本篇文章正文内容,下面案例可供参考

一、信号

可以简单理解为信号是一个进程给另一个信号发消息,进程收到对应的信号就执行对应的方法,linux信号可以分为实时信号和非实时信号

1-31为非实时信号,34-64为实时信号,t它们是宏定义,写数字或者信号名称都可以,不过1-31号信号大部分都是中止进程,用命令:man 7 signal可查看信号的作用

特点:信号的产生是随机性,非实时信号可以被进程临时保留,到合适的时候处理

二、信号的捕捉和处理

1.signal()

用系统函数signal捕捉信号,通过回调函数处理信号。 以前如果进程收到信号,就会执行系统对应的方式处理信号,但是我们通过这个函数,可以捕捉特定信号,自定义处理信号,以下例子,参数为2号信号中止进程,进程收到2号信号,信号被捕捉,执行handsingle函数然后调用exit(0)中止进程。

没有收到2号信号就不会执行方法

我们也可以忽略这个信参数为SIG_IGN .忽略这个信号是进程收到这信号特殊处理

2.sigaction()

#include <signal.h>

int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);

signo 是捕捉的信号,act是一个结构体,我们设置是非实时信号,所以只要设置如下参数,用函数sigaddset添加要要堵塞的信号到sa_mask.

这里我们可以看到现象是,如果我们发送2号信号,那么就执行hanlder方法,执行方法过程中如果进程还收2号信号,那么就会对2号信号进行堵塞。我们发送3和4号(sa_mask),也会堵塞pending一直为1.

三.信号的发生方式:

1.键盘(硬件)

如果对一个进程失去控制ctrl+C或者ctrl+/,中止这个进程,Linux就会发送SINGINT/SINGQUITG给进程。

硬件到软件:cpu中有很多引脚,键盘按下触发高电平硬件中断,cpu内的寄存器就会记录下中断号,系统通过寄存器再通过中断向量表(实际是一个函数指针数组),执行读取方法,如果是普通字符就读取数据到文件缓冲区,识别是ctrl+/等就会发生信号给进程。

2.命令行

kill 杀死进程:kill -9 pid

实际上是封装了kill()系统函数

3.系统函数

kill/raise/abort():kill()可以杀死任意进程,raise哪个进程调用就给自己发信号(中止),abort()中止进程

4.异常

例如除零异常,野指针

除零异常:cpu寄存器计算的时候,如果出现除零异常就会将状态寄存器置为1,操作系统就会发信号给进程。

野指针:linux中通过页表的将虚拟地址映射到物理地址,虚拟地址转化为物理地址,是通过硬件MMU转换,转化失败,就会有寄存器记录信息,系统通过寄存器的状态发生信号给进程

5.软件条件

1.管道

比如说以2个进程分别读写方式打开管道,如果读端关闭,那么写端的进程就会收到信号就会退出,如果读端在管道没有读取到数据同时写端打开还没写,那么读端就会收到信号进行堵塞等待,直到管道中有数据。

2.alarm()定时器

alarm()中设置秒数,时间到了就会发 SIGALRM信号给进程,它的返回值是剩余时间的秒数,如果设置5秒,在这个期间又设置了2秒,闹钟提前了,这时就会返回3。(5秒时间没到,2秒的时候闹钟提前了),alarm(0)是取消之前设定的闹钟

四.信号的保存

1.修改block

一个进程的地址空间中维护3张表,进程收到信号实际是操作系统修改进程的表数据,block是堵塞状态位图,pending是未决状态位图,handler是信号的处理方式,是类型是一个函数指针。内核提供了信号集操作函数.

#include <signal.h>
int sigemptyset(sigset_t *set);//清空
int sigfillset(sigset_t *set);
int sigaddset (sigset_t *set, int signo);//添加
int sigdelset(sigset_t *set, int signo);//删除
int sigismember(const sigset_t *set, int signo);//判断pending位是否为1.
函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含 任何有
效信号。
函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示 该信号集的有效信号包括系
统支持的所有信号。
注意,在使用sigset_ t类型的变量之前,一定要调 用sigemptyset或sigfillset做初始化,使信号集处于确定的
状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信

  

sigset_t是一个结构体类型,block和pending数据是1或0,linux用sigset_t结构体类型来表示,

#include <signal.h>

int sigprocmask(int how, const sigset_t *set, sigset_t *oset);返回值:若成功则为0,若出错则为-1。

这个是how的参数,决定是否对信号进行堵塞或者解除堵塞状态,set是你添加的block,old是原来的block(通过它可以拿到之前的)

sigset_t newblock,oldblock;//初始化blocksigemptyset(&newblock);sigemptyset(&oldblock);//添加2信号(堵塞)//sigaddset(&newblock,2);//设置当前进程的block,屏蔽2号信号sigprocmask(SIG_SETMASK,&newblock,&oldblock);

 ,我们可以用这个函数堵塞一些信号,不过不是所有信号都可以屏蔽,比如9号信号或19。对信号进程堵塞,如果进程收到我们堵塞的信号,那么对应的pending一直是1,那它也不会执行handler方法,除非解除堵塞

2.pending的获取

pending表的获取,linux提供了系统函数判断是否信号是否未决。

3.信号的丢失

如果父进程同时收到 大量的子进程退出的信号(来不及处理覆盖了),那么它只会保留一个,父进程回收的时候就会造成大量的僵尸进程,

1.父进程等待回收

(1)堵塞式等待和非堵塞 式等待。

堵塞等待:不好的地方是,进程很多的话,有的进程不退出,那么它无法回到主进程。

非堵塞等待:子进程退出,那么会通知父进程进行回收,如果没有进程退出就会 结束等待。

2.直接忽略信号,进程退出不会造成僵尸进程

五,信号的处理时机

内核态和用户态:

当出现中断或者系统调用进程调度,就会进入内核态,处理完中断或者异常就会处理当前进程的收到的信号。如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了SIGQUIT信号的处理函数sighandler。 当前正在执行main函数,这时发生中断或异常切换到内核态。 在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT递达。 内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函 数,sighandler和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是 两个独立的控制流程。 sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态。 如果没有新的信号要递达,这次再返回用户态就是恢复main函数的上下文继续执行

六,关键字volatile

从内存中读取数据,而不是因为编译器优化的原因,从寄存器中读取

int flag = 0;
//volatile int flag = 0
void handler(int sig)
{
printf("chage flag 0 to 1\n");
flag = 1;
}
int main()
{
signal(2, handler);
while(!flag);
printf("process quit normal\n");
return 0;
}

标准情况下,键入 CTRL-C ,2号信号被捕捉,执行自定义动作,修改 flag=1 , while 条件不满足,退出循环,进程退出,但是编译器优化后,将内存中的flag放入寄存器中,自定义动作修改了内存但是寄存器中并没有,进程不退出,关键字可以避免优化。

七.不可重入函数

例子:链表的插入:mian函数调用这个函数对全局链表进行插入操作,insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入,insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为 不可重入函数,反之,如果一个函数只访问自己的局部变量或参数,则称为可重入(Reentrant) 函数。。

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

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

相关文章

计算机精选期刊特辑

文章目录 一、征稿简介二、合作期刊三、投稿咨询四、咨询 一、征稿简介 艾思科蓝依托互联网信息与数据库技术、整合渠道与合作资源&#xff0c;提供EI/SCI/SCIE/SSCI期刊论文的内容审查、发表支持等服务。艾思科蓝与多所知名出版社达成战略合作关系&#xff0c;持续开展合作征…

利用神经网络学习语言(一)——自然语言处理的基本要素

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 本文涉及到的代码链接如下&#xff1a;regression2chatgpt/ch10_rnn/tokenizer.ipynb 本系列文章将深入探讨一种应用广泛的神经…

syncthing文件夹同步与版本管理

1 前言 syncthing可以用来同步文件夹里的所有文件&#xff0c;并且有不错的版本管理&#xff0c;基本每次更改文件&#xff0c;20-40秒就被扫描到了&#xff0c;非常丝滑&#xff1b;这次以此来同步obsidian的插件和文件&#xff0c;达到多端同步&#xff1b; 我家里有一台台…

Android HAL到Framework

一、为什么需要Framwork? Framework实际上是⼀个应⽤程序的框架&#xff0c;提供了很多服务&#xff1a; 1、丰富⽽⼜可扩展的视图&#xff08;Views&#xff09;&#xff0c; 可以⽤来构建应⽤程序&#xff0c;它包括列表&#xff08;lists&#xff09;&#xff0c;⽹格&am…

闲话 .NET(4):为什么要跨平台?

前言 .NET Core 有一个关键词就是跨平台&#xff0c;为什么要跨平台呢&#xff1f;Windows 操作系统不香吗&#xff1f;今天我们来聊聊这个 原因一&#xff1a;安全考虑 Windows OS 是闭源的&#xff0c;而 Linux 是开源的&#xff0c;因此有些公司的技术负责人就认为 Linux…

如何将老板的游戏机接入阿里云自建K8S跑大模型(下)- 安装nvidia/gpu-operator支持GPU在容器中共享

文章目录 安装nvidia/gpu-operator支持GPU在容器中共享 安装nvidia/gpu-operator支持GPU在容器中共享 安装 nvidia/gpu-operator遇到两个问题&#xff1a; 由于我们都懂的某个原因&#xff0c;导致某些镜像一直现在不成功。 解决办法&#xff0c;准备一个&#x1fa9c;&#…

车间人员作业行为智能检测 AI视觉在生产车间制造中的应用

车间人员作业行为智能检测系统基于神经网络人工智能视觉算法&#xff0c;车间人员作业行为智能检测通过对车间监控摄像头获取的视频图像进行分析和识别&#xff0c;实现了对人员操作行为的智能检测。系统对工人的操作环节进行分解&#xff0c;根据时间、动作标准等方面制定了规…

MemoryDB 2024 论文分享

论文地址点这里。 TL;DR MemoryDB 通过底层依赖 AWS 内部系统 Multi-AZ Transaction Log 实现了 11 个 9 的持久性保证。 通过依赖 Transaction Log 的 Condition API 和租约机制来实现了一致性和可用性保证。 通过周期性调度 Off-box 节点来外部 Rewrite binlog 避免了内存…

C语言基础——循环(2)+关机程序

欢迎点赞支持 个人主页&#xff1a;励志不掉头发的内向程序员&#xff1b; 专栏主页&#xff1a;C语言基础&#xff1b; 文章目录 目录 前言 一、for循环的补充 二、循环的嵌套 1、嵌套的介绍 1.1 练习&#xff1a; 题目解析&#xff1a; 优化&#xff1a; 三、goto语句 1、go…

3DEXPERIENCE DELMIA Role: RFP - Fabrication Robot Programmer

Discipline: Robotics Role: RFP - Fabrication Robot Programmer 在虚拟工厂中定义、验证和编程机器人弧焊和密封剂沉积系统 模拟和验证完整的焊接、密封剂沉积和搬运机器人系统&#xff0c;以消除代价高昂的碰撞并优化生产率提供精确的生产就绪型机器人程序&#xff0c;同…

Day 38 防火墙技术IPtables

一&#xff1a;防火墙简介 1.简介 ​ iptables其实并不是真正的防火墙&#xff0c;我们可以把他理解为一个客户端的代理&#xff0c;用户是通过iptables这个代理&#xff0c;将用户的安全设定执行到对应的“安全框架”中&#xff0c;这个“安全框架”才是真正的防火墙。这个框…

mac安装Redis

官网&#xff1a; https://redis.io中文网&#xff1a; Redis中文网 安装 brew install redis 查看版本 redis-server --version 开启关闭服务 方式一&#xff08;不推荐&#xff09; 这种方式不太建议&#xff0c;因为控制台不用输出相应的日志 开启服务 brew service…

K8S认证|CKA题库+答案| 1. 权限控制RBAC

1、权限控制RBAC 您必须在以下Cluster/Node上完成此考题&#xff1a; Cluster Master node Worker node k8s master …

园区网的基本了解

园区网使用的典型技术---IEEE802.3标准/IEEE802.11标准 封闭式园区网络 ---由内部人员使用&#xff0c;不能访问互联网。 ---制订各式各样的规章制度 ---NAC&#xff0c;网络接入控制 开放式园区网络 ---服务于公众的&#xff0c;认证 园区网的发展 第一代&#xff1a;…

神经网络模型结构和参数可视化

神经网络模型结构和参数可视化 一、前言二、Netron2.1Netron简介2.2TensorFlow、Keras、Caffe模型文件实测结果2.3PyTorch、scikit-learn模型文件实测结果 三、NN-SVG四、Netscope五、PlotNeuralNet六、Graphviz七、总结参考文档 一、前言 在神经网络的某些应用场景中&#xf…

.NET快速实现网页数据抓取

网页数据抓取需求 本文我们以抓取博客园10天推荐排行榜第一页的文章标题、文章简介和文章地址为示例&#xff0c;并把抓取下来的数据保存到对应的txt文本中。 请求地址&#xff1a;https://www.cnblogs.com/aggsite/topdiggs 创建控制台应用 创建名为DotnetSpiderExercise的控…

【Spring security】【pig】Note01-pig登录验证过程

&#x1f338;&#x1f338; pig 登录验证 &#x1f338;&#x1f338; pig后端源码 一、大概执行顺序&#xff0c;便于理解 pig spring-security 二、配置过滤器 配置SecurityFilterChain 三、执行过程分析 请求拦截&#xff1a; 当客户端发送请求时&#xff0c;Sprin…

Kubernetes——Pod详解

目录 一、Pod基础概念 1.概念 2.使用方式 3.Pause容器 3.1网络 3.2存储 4.Pod容器分类 4.1自主式Pod 4.2控制器管理的Pod 二、Pod的分类 1.基础容器&#xff08;infrastructure container&#xff09; 2.初始化容器&#xff08;initcontainers&#xff09; 2.1Ini…

CR80清洁卡都能用在什么地方?

CR80清洁卡&#xff08;也被称为ISO 7810 ID-1清洁卡&#xff09;的规格确实使其在各种需要读取磁条或接触式智能卡的设备中都有广泛的用途。这些设备包括但不限于&#xff1a; ATM自动终端机&#xff1a;当ATM机的磁条读卡器出现故障或读卡不灵敏时&#xff0c;可以使用CR80清…

Python 渗透测试:MySQL 数据库 弱密码测试.(3306 端口)

什么是 MySQL 数据库 MySQL 是一种开源的关系型数据库管理系统(RDBMS)。它是目前世界上最流行的数据库之一,被广泛应用于各种类型的网站和应用程序中。MySQL 数据库爆破是一种非法和危险的黑客攻击手段。它指的是通过暴力猜测密码的方式,试图获取未授权访问 MySQL 数据库的行为…