Linux进程信号产生以及捕捉

news2024/11/22 21:20:42

一.什么是信号

生活中,有哪些信号相关的场景呢,比如:红绿灯,闹钟,转向灯等等

1.这里我们要知道,你为什么认识这些信号呢,记住了对应场景下的信号+后续是有”动作“要你执行的

2.我们在我们的大脑中,能够识别这个信号的

3.如果特定信号没有产生,但是我们依旧知道应该如何处理这个信号

4.我在收到这个信号的时候,可能不会立即处理这个信号

5.信号本身,在我们无法立即被处理的时候,也一定要先被临时的记住

 结论:什么是Linux信号,本质是一种通知机制,用户or操作系统通过发送一定的信号,通知进程,某些事件已经发生,你可以在后续进行处理。

二.信号如何使用,结合进程,信号结论

1.进程要处理信号,必须具备信号“识别”的能力(看到+处理动作)

2.凭什么进程能够“识别”信号呢,代码是程序员编写的,就比如说你是如何认识红绿灯的,这都是有人告诉你的

3.信号产生是随机的,进程可能正在忙自己的事情,所以,信号的后续处理,可能不是立即处理的

4.进程会临时的记录下对应的信号,方便后续进行处理

5. 在什么时候处理呢,合适的时候(这个后面会说)

6.一般而言,信号的产生相对于进程而言是异步的(什么是异步呢,异步双方不需要共同的时间,也就是接收方不知道发送方什么时候发送,所以在发送的信息中就要有提示接收方开始接收的信息,如开始时有开始位,同时在结束时有停止位。)

三.信号常见的处理方式

1.默认(进程自带的,程序员写好的逻辑)

2.忽略(信号的一种处理方式)

3.自定义动作(捕捉信号)

四.常见信号

 1-31普通信号,34-64实时信号。

如何理解组合键变信号:键盘的工作方式是通过:中断方式进行的,当然也能够识别组合键,ctrl+c,OS解释组合键->查找进程列表->前台运行的进程->OS写入对应的信号到进程内部的位图结构中。 

如何理解信号被进程保存:进程必须具有保存信号的相关数据结构(位图,unisgned int)PCB内部保存了信号位图字段。

如何理解信号发送的本质:信号位图是在task_struct -> task_struct内核数据结构->OS。

信号发送的本质:OS向目标进程写信号,OS直接修改pcb中的指定的位图结构完成“发送”信号的过程。

五.信号的产生以及核心转储

 键盘产生信号

 sighandler_t handler回调函数,通过回调的方式,修改对应信号的捕捉方法,signum,要捕捉信号的名称或编号。

#include<iostream>
#include<signal.h>
#include<unistd.h>
#include<sys/types.h>
using namespace std;


void cating(int signum)
{
    cout<<"捕捉到信号:"<<signum<<endl;

    return;
}

int main()
{
    signal(2,cating);
    while(1)
      sleep(1);
    return 0;
}

signal(SIGINT,catchsig),特定信号的处理动作,一般只有一个,signal函数,仅仅是修改进程对特定信号的后续处理动作,不是直接调用对应的处理动作,如果后续没有任何SIGINT信号产生,catchsig永远也不会被调用。

核心转储

man 7 signal 查看信号的默认处理行为。这里不同信号的Action不同,有Term、Core、Ign、Cont、Stop等状态行为。

接下来就是了解一下Core动作——核心转储(一般而言云服务器的核心转储功能是被关闭的)。关于进程等待中,status 中如果是正常终止就保存返回值、错误码。

如果被信号所杀,第7位上保存的这个就叫做core dump,如果是0表示没有发生核心转储,为1则是发生了核心转储。我们可以打印code_dump位的信息 (左移7位然后与上1即可)。 

#include<iostream>
#include<signal.h>
#include<unistd.h>
#include<sys/types.h>
using namespace std;


void cating(int signum)
{
    cout<<"捕捉到信号:"<<signum<<endl;

    return;
}
int main()
{
    pid_t id = fork();
    if (id == 0)
    {
        sleep(1);
        int a = 100;
        a /= 0;
        exit(0);
    }
    int status = 0;
    waitpid(id, &status, 0);
    cout << "父进程:" << getpid() << "子进程:" << getppid() << endl;
    //退出信号:
    cout << "exit sig" << (status & 0x7f) << endl;
    // 打印core dump位
    cout << "core dump" << (status > 7 & 1) << endl;
}

如果核心转储是被关闭的,可以使用ulimit -a查看,ulimit -c10240打开,这里就可以使用core.11077就可以定位错误。

系统调用发送信号 

 第一个参数为指定的进程pid,第二个参数为对应的信号编码。

kill 是给指定进程发送信号,而如果想让自己给自己发信号,可以使用 raise 命令

给自己发送abort信号,也就是6号信号。相当于代码:raise(6) 或  kill(getpid(),6)

软件条件产生信号

这里可以举一个例子:当管道,读端不进行读取,还关闭了文件描述符,而写端一直写入,会发生什么问题?操作系统会自动终止对应写端进程,通过发送信号的方式,发送SIGPIPE信号。

 验证:

1.创建匿名管道

2.让父进程进行读取,子进程进行写入

3.让父进程关闭读端 && waitpid(),子进程一直进行写入

4.子进程退出,父进程waitpid拿到子进程的退出status。

5.提取退出信号。

SIGPIPE便是一种软件条件产生的信号,除了管道中会发出SIGPIPE信号,接下来我们学习其它软件产生的信号,alarm 函数与SIGALRM 信号,系统调用中的 alarm 函数会产生 SIGALRM  信号。接下来让我们了解一下 alarm 接口。

调用 alarm 函数可以设定一个闹钟,也就是告诉内核再 seconds 秒之后给当前进程发 SIGALRM 信号,该信号的默认处理动作是终止当前进程。 

利用上面这个函数,我们可以做一个定时器。

int count = 0;
 
void catchSig(int signum)
{
    cout << "count: " << count << endl;
}
int main()
{
    // 1秒后发送消息
    alarm(1);
    signal(SIGALRM, catchSig);
    while (1)
    {
        ++count;
    }
    return 0;
}

如何理解软件条件给进程发送信号OS先识别到某种软件条件触发或不满足。OS构建信号,发送给指定的进程。

 硬件异常产生信号

 首先我们要知道硬件是如何产生信号的,我们先写一段整数除以0的代码看一下。

void handler(int signum)
{
    sleep(1);
    cout << "signal is : " << signum << endl;
}
int main()
{
    signal(SIGFPE, handler);
    int a;
    a/=0;
    while (1)
        sleep(1);
    return 0;
}

这段代码会不断的产生信号8,但是我们把信号8捕捉了,他就会不停的发送。

一.那如何理解整数除以0这个操作

1.因为计算的是CPU,如果CPU计算出现错误,会将错误信息放入到状态寄存器中,状态寄存器中有对应的状态标记位(类比成 位图),其中会存在溢出标记位,OS会自动进行计算完毕之后的检查。
2.如果OS识别到有溢出问题,根据 current指针(指向当前正在运行的进程) 找到进程,然后提取出 PID,O S再进行信号发送到该进程,进程则会再合适的时候,进行信号的处理。
3.立即找到当前 task_struct中有一个current指针,当程序进行执行时,current内的内容也会被加载到CPU的寄存器中。
4.所以,整数除以零是一个硬件异常的问题。

二·.那一旦出现硬件异常,进程一定会退出吗?

不一定,一般默认是退出,但是如果我们不进行退出,我们也不能进行任何操作,因为无权访问CPU中的寄存器数据。

三.为什么会发生死循环?

因为寄存器中的异常一直没有被解决,所以一般我们出现除0等错误,一般就直接exit()退出了。

指针越界、野指针一般被称为段错误 (11号信号SIGSEGV)

那如何理解野指针或越界问题?

1.都必须通过地址,找到目标位置,
2.语言上的地址,全部都是虚拟地址
3.将虚拟地址转化为物理地址
4.页表+MMU(Memmory Manager Unit——硬件)
5.野指针,越界->非法地址->MMU转化的时候,一定会报错。因为MMU这个硬件其中也有寄存器,注意,外设也有寄存器的,不只是CPU有寄存器。

 结论:硬件也能产生信号。所有的信号,都有其来源,但最终全部都是被OS被识别、解释、发送的。

信号的常见问题

为什么所有的信号产生,最终都要由OS来执行?
因为OS是进程的管理者。

信号的处理是否是立即处理的?
由OS在合适的时机进行处理。

信号如果不是被立即处理,那么信号是否需要暂时被进程记录下来?记录在哪里?
需要被记录下来,记录在进程PCB中对应的信号记录位图。

如何理解OS向进程发送信号?
本质是OS直接修改PCB中的信号位图,根据信号编号修改特定的比特位(由0置1)。

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

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

相关文章

spring boot 项目打包镜像方式以及区分环境打包

springboot项目打包成docker镜像-贾玉珍-2023年2月8日方法一&#xff1a;将项目jar包手动推送到docker服务器上1.用maven对项目进行打包&#xff0c;打包成功后会有一个target目录&#xff0c;目录下有打好的项目jar包2.将jar包上传到服务器上&#xff0c;我用的是finalshell工…

Zabbix Agent item监控项讲解

前言 agent与snmp是Zabbix两种重要的监控方式&#xff0c;这一期主要介绍Zabbix Agent item监控项。。Zabbix agent分为主动代理、被动代理&#xff0c;配置item类型时&#xff0c;可以选择需要的类型&#xff1a; Zabbix agent &#xff1a;用于被动检查 Zabbix agent&…

【C语言进阶】结构体、位段、枚举和联合

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前是C语言学习者 ✈️专栏&#xff1a;C语言航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&a…

顶刊MS论文解读|数据驱动的动态定价和订购策略

作者&#xff1a;白静 金凯瑞 马玺渊 钟子俊编者按 本次解读的文章为“Data-Driven Dynamic Pricing and Ordering with Perishable Inventory in a Changing Environment”&#xff0c;于2022年发表在期刊 Management Science, 作者 N. Bora Keskin, Yuexing Li, Jing-Sheng …

推荐5款极大提高工作效率的办公软件!每个都是我精挑细选的

关于提高办公效率的相关软件&#xff0c;答主要把工作5年的独家秘方都拿出来了。分享的都是用过的且体验不错的软件&#xff0c;大多数是免费软件&#xff01; 按照使用场景&#xff0c;简单先分个类&#xff0c;分别是时间利用利器&#xff0c;流程优化软件&#xff0c;办公美…

论文投稿指南——中文核心期刊推荐(工程材料学)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

重生之我是赏金猎人-SRC漏洞挖掘(一)-某SRC测试系统无脑Getshell

0x01 前言 https://github.com/J0o1ey/BountyHunterInChina 欢迎大佬们点个star 0x02 资产收集到脆弱系统 在某src挖掘过程中&#xff0c;本人通过ssl证书对域名资产进行了收集&#xff0c;通过计算域名对应ip段的权重 整理出其C段资产&#xff0c;进行了批量目录扫描 查看…

Spring Boot两种格式的配置文件,你都了解吗?

目录 前言 一、properties配置文件 1.1、语法格式 1.2、读取配置文件 1.3、缺点分析 2、yml配置文件 2.1、yml语法 2.1.1、注意&#xff1a;value值的单双引号 2.2、yml配置读取 2.3、yml配置的不同数据类型 2.4、yml配置对象 2.5、yml配置集合 3、面试&#xff1a…

2023年浙江道路运输安全员考试真题题库及答案

百分百题库提供道路运输安全员考试试题、道路运输安全员考试预测题、道路运输安全员考试真题、道路运输安全员证考试题库等,提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 1.关于道路运输企业车辆技术管理机构的主要职责&#xff0c;在下列表述中最…

anaconda3文件夹被移动之后,如何操作可以复用原有conda环境

anaconda3文件夹被移动A-调整conda PATH地址B-更改.conda/environments.txt中的地址C-修改conda内的变量和每个环境的pip目录A-调整conda PATH地址 B-更改.conda/environments.txt中的地址 a. 优先切换到用户根目录 b. 查看隐藏conda目录 c. 编辑 vi .conda/environments.txt…

【服务器数据恢复】NetApp存储无法访问的数据恢复案例

服务器数据恢复环境&#xff1a; NetApp某型号存储&#xff1b; 配备SAS硬盘&#xff0c;该硬盘520字节一个扇区&#xff1b; 所有的lun映射到小型机使用&#xff0c;存放Oracle数据库文件&#xff0c;采用ASM裸设备存储方式。 服务器故障&#xff1a; 管理员误操作删除NetApp…

介电常数常用测量方法综述

张扬1&#xff0c;徐尚志1&#xff0c;赵文晖2&#xff0c;龚增2&#xff0c;赵晓群1 1同济大学&#xff0c;上海 2上海市计量测试技术研究院&#xff0c;上海 在设计电路、天线、电容器等过程中经常会涉及所用材料的介电常数, 所以深入了解介电常数的相关概念对实际工作有重…

【RuoYi-Vue-Plus】学习笔记 48 - 数据加密功能 Encrypt 源码分析

文章目录前言参考目录功能实现的准备知识1、目录结构说明2、一些准备知识2.1、自定义插件如何实现&#xff1f;2.2、Mybatis 拦截器的拦截点&#xff1f;2.3、关于 Intercepts 注解&#xff1f;2.4、关于拦截器中的 Interceptor() 方法和 plugin() 方法&#xff1f;功能调用流程…

企业数字化转型中信息化是什么

数字化转型带给企业的价值无疑是能够支撑起这股热潮的&#xff0c;这种流行趋势在数字化时代也并不意外。不过有一点值得注意&#xff0c;那就是数字化转型毕竟发展时间还不太长&#xff0c;虽然有未来加持&#xff0c;但又有多少企业能够在当下坚持数字化转型&#xff0c;顺利…

MYSQL的第四次索引视图

题目&#xff1a; 学生表&#xff1a;Student (Sno, Sname, Ssex , Sage, Sdept) 学号&#xff0c;姓名&#xff0c;性别&#xff0c;年龄&#xff0c;所在系 Sno为主键 课程表&#xff1a;Course (Cno, Cname,) 课程号&#xff0c;课程名 Cno为主键 学生选课…

[数据库迁移]-MySQL常见问题

[数据库迁移]-MySQL常见问题 森格 | 2023年2月 介绍&#xff1a;记录在MySQL数据库迁移过程中遇到的问题&#xff0c;以及解决方案。 文章目录[数据库迁移]-MySQL常见问题一、背景二、常见问题2.1 ERROR 20032.2 ERROR 12732.3 ERROR 10712.4 视图权限2.5 ERROR 1062三、总结一…

idea提交git时过滤掉不必要的文件 mes

.ignore插件的安装非常简单&#xff0c;如下图所示&#xff1a; 1.添加.gitignore 在项目上创建 在打开的面板中&#xff0c;执行如下图所示的选择&#xff1a; 3.在本地项目下文件上创建需要过滤文件后缀名 ### Example user template template ### Example user templa…

算法笔记(五)—— 二叉树

链表练习题&#xff1a; 1. 查两个链表的第一个入环结点&#xff0c;loop1,loop2。&#xff08;快慢指针&#xff0c;相交后&#xff0c;快指针放头节点&#xff09; 2. 当loop1null , loop2null时 如果两个链表最后一个结点不相等&#xff0c;那么一定不相交。 最后一个结点地…

Allegro如何设置最大撤回步数操作指导

Allegro如何设置最大撤回步数操作指导 在做PCB设计的时候,偶尔会出现误操作或者简单评估需要撤回到原来的状态,避免返工。Allegro支持撤回操作,用菜单的Undo命令即可实现 同样还支持设置最大的撤回步数,具体操作如下 点击Setup点击User Preferences

C语言(ctype.h系列的字符函数)

1.字符测试函数 函数名 如果时下列函数时&#xff0c;返回值为真 Isalnum&#xff08;&#xff09; 字母或数字 isalpha&#xff08;&#xff09; 字母 isblank&#xff08;&#xff09; 标准的空白字符&#xff08;空格&#xff0c;水平制表符或换行符&#xff09;或任…