Linux进程信号(一)

信号产生

  • 1.信号基础知识
  • 2.初步认识信号
  • 3.signal函数
  • 4.技术应用角度的信号
  • 5.调用系统函数向进程发信号
  • 6.由软件条件产生的信号
  • 7.硬件异常产生信号
  • 8.core

🌟🌟hello,各位读者大大们你们好呀🌟🌟
🚀🚀系列专栏:【Linux的学习】
📝📝本篇内容:信号基础知识;初步认识信号;signal函数;技术应用角度的信号;调用系统函数向进程发信号;由软件条件产生的信号;硬件异常产生信号;core
⬆⬆⬆⬆上一篇: 进程间通信
💖💖作者简介:轩情吖,请多多指教(>> •̀֊•́ ) ̖́-

1.信号基础知识

1.信号没有产生,进程也知道该怎么处理它
2.进程在没有收到信号的时候,它就已经能够认识并处理一个信号。程序员设计进程的时候,早就设计了对信号的识别能力
3.信号可能随时产生,所以在信号产生前,进程可能在做优先级更高的事情,可能不能立马处理这个信号,只能在后续合适的时候处理,因此进程收到信号时,需要进程具有记录信号的能力,保存起来
4.信号的产生对于进程来说是异步的(信号产生归产生,进程执行自己的代码)
5.1-31:普通信号 34-64:实时信号
在这里插入图片描述
6.进程的task_struct内部必定存在一个位图结构,用int表示;uint32_t signals;比特位的位置是信号的编号;比特位的内容是指是否收到该信号(0,1)
7.所谓的发送信号,本质其实是写入信号,直接修改特定进程的信号位图中的特定比特位,0->1
8.信号产生之后,不是立即处理,而是在合适的时候
9.处理信号的方式:①默认动作 ②忽略信号 ③ 用户自定义动作

2.初步认识信号

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;
int main()
{while (1){cout << "我是一个进程,我在执行。。。" << endl;sleep(1);}return 0;
}

在这里插入图片描述

一般执行的进程都是前台进程,不执行时bash为前台进程,因此执行时输入指令无法识别。当执行进程时后面加一个&,为后台进程
在这里插入图片描述
但此时要想要退出这个进程只能使用kill -9来杀掉,用别的比如ctrl^c都不行
在这里插入图片描述
其实不管用kill -9还是ctrl^c都是向进程发送了信号,kill -9发送的是9号信号,而ctrl+c是2号信号

3.signal函数

在这里插入图片描述
signal函数可以用来对指定的信号设定自定义处理动作,它的第二个参数就是把对应的处理动作传过去,它的第一个参数是对应要处理的信号,来看下面的例子,我们自定义一下2号信号的处理方式

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;
void handle(int signo)
{
cout<<"我是对应的"<<signo<<"信号"<<endl;
}
int main()
{cout<<"pid:"<<getpid()<<endl;signal(2,handle);while (1){cout << "我是一个进程,我在执行。。。" << endl;sleep(1);}return 0;
}

在这里插入图片描述
可以发现我们使用kill -2时,它对应的处理方法是我们所自定义的,其实2号信号就是ctrl+c,我们的2
号信号的默认处理动作是终止进程

①signal(2,handle)调用这个函数的时候,handle方法并没有被调用,只是更改了2号信号的处理动作,handle方法只有在2号信号产生的时候才被调用
②默认我们对2号信号的处理动作:终止进程,我们用signal函数,我们在执行用户自定义动作的捕捉
③handle的int参数是特定信号被发送给当前进程的时候,执行handle方法的时候,自动填充对应的信号编号

我们甚至可以给所有的信号设置同一个处理函数,但9号信号不受影响

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;
void handle(int signo)
{
cout<<"我是对应的"<<signo<<"信号"<<endl;
}
int main()
{cout<<"pid:"<<getpid()<<endl;for(int i=1;i<=31;i++){signal(i,handle);}while (1){cout << "我是一个进程,我在执行。。。" << endl;sleep(1);}return 0;
}

在这里插入图片描述
在这里插入图片描述

4.技术应用角度的信号

用户输入命令,在shell下启动一个前台进程。用户按下ctrl+c,这个键盘输入产生一个硬件中断,被OS获取。解释成信号,发送给目标前台进程。前台进程因为收到信号进而引起进程退出。
硬件中断的理解:当键盘按下时,通过类似8259硬件给CPU的脚针发送脉冲,其中脚针有对应的中断号,在系统中存在中断向量表,向量表中存的是对应的函数指针,中断号是向量表的下标,通过函数得知键盘哪些位置被摁下,此时OS得知了ctrl+c的按下,解释成了一个信号2,找到前台进程向其写入2号信号

5.调用系统函数向进程发信号

函数一:
在这里插入图片描述
kill命令是调用kill函数实现的,kill函数可以给一个指定的进程发送指定的信号

//模拟实现kill命令
#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <cstdlib>
using namespace std;
int main(int argc,char* argv[])
{if(argc!=3){cout<<"格式是:kill -sign pid"<<endl;exit(1);}int pid=atoi(argv[2]);//atoi函数用来把字符串转换成整数int signo=atoi(argv[1]);int ret=kill(pid,signo);if(ret!=0){cout<<"kill fails"<<endl;exit(2);}return 0;
}

在这里插入图片描述
在这里插入图片描述
函数二:
在这里插入图片描述
这个函数可以给当前进程发送指定的信号(自己给自己发信号)

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;
int main()
{int cnt=5;while(cnt--){cout<<cnt<<endl;sleep(1);}raise(2);//五秒后进程自己给自己发2号信号cout<<"发送信号失败"<<endl;//如果正常发送就不能看见这句话return 0;
}

在这里插入图片描述
函数三:
在这里插入图片描述
absort()不会因为信号捕捉而导致无法终止,在执行完自定义处理方法后立马终止

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;void handle(int signo){cout<<"我是对应的"<<signo<<"信号"<<endl;}
int main()
{   handle(SIGABRT);//对应的信号是6 abort();return 0;
}

在这里插入图片描述
就像exit函数一样,abort函数总会成功

6.由软件条件产生的信号

在这里插入图片描述
调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒后给当前进程发SIGALRM信号,该信号的默认处理动作是终止当前进程
这个函数的返回值是0或者是以前设定的闹钟时间还剩下的秒数。如果seconds为0,表示取消以前设定的闹钟,返回值依然是以前设定的闹钟时间还剩下的秒数

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;void handle(int signo){cout<<"我是对应的"<<signo<<"信号"<<endl;}
int main()
{signal(SIGALRM,handle);int cnt=10;alarm(5);//五秒后会调用自定义处理方法handlewhile (cnt--){cout<<cnt<<endl;sleep(1);}return 0;
}

在这里插入图片描述

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;void handle(int signo){cout<<"我是对应的"<<signo<<"信号"<<endl;}
int main()
{int cnt=5;alarm(10);while (cnt--){cout<<"倒计时:"<<cnt<<endl;sleep(1);}cout<<"alarm返回值"<<alarm(5)<<endl;return 0;
}

在这里插入图片描述
OS中有数据结构(小堆)来存闹钟,在堆顶的是距离现在最近的时间
每个进程只有一个闹钟

7.硬件异常产生信号

硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号
①当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释为SIGFPE信号发送给进程
在这里插入图片描述
可以发现编译的时候会报警告,但是运行时直接终止了
在这里插入图片描述
②当前进程访问了非法内存地址,MMU会产生异常,内核将这个异常解释为SIGEGV信号发送给进程

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;
void handle(int signo)
{cout << "我是对应的" << signo << "信号" << endl;
}
int main()
{int *p=nullptr;*p=10;return 0;
}

在这里插入图片描述

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;
void handle(int signo)
{cout << "我是对应的" << signo << "信号" << endl;
}
int main()
{int *p;*p=10;return 0;
}

在这里插入图片描述
在这里插入图片描述
其实本质上第一步并不是直接写入100,而是先通过MMU进行虚拟地址到物理地址的转换,如果没有映射,MMU硬件报错,有映射,但没有权限,MMU直接报错,MMU报错后OS能检测到

上面两种情况都使用自定义捕捉,会出现死循环,因为当硬件出现了异常,被OS捕捉到后,会给对应的进程发信号的,但是进程没有做出什么反应,因为当CPU又执行这个进程时,异常还在,OS继续给进程发信号,所以导致了死循环

8.core

在这里插入图片描述
这当中大多数信号都是终止,但是为什么有term和core的区别?
core:终止,会先进行核心转储,然后再终止进程
term:终止就是终止,没有多余动作
之前进程退出部分中的core dump标志是为了表示是否发生核心转储
在这里插入图片描述
OS可以将该进程在异常的时候,核心代码部分进行核心转储,将内存中的进程相关数据全部dump到磁盘中,一般核心转储文件在云服务器看不到,因此默认关闭这个功能的,因为我们的是生产环境,怕多次运行,导致core文件过多
查看核心转储命令:ulimit -a
修改核心转储:ulimit -c 大小
在这里插入图片描述
在这里插入图片描述
此时在运行我们的代码

    #include <iostream>#include <sys/types.h>#include <signal.h>#include <cstdlib>#include <unistd.h>using namespace std;int main(){int a=10;a/=0;return 0;}

在这里插入图片描述
在这里插入图片描述
可以发现我们当前目录下多了一个core文件
那这个core文件有什么用呢?
可以通过核心转储在异常后·1,方便进行调试,在gdb通过core-file 文件名进行自动定位
在这里插入图片描述

🌸🌸信号产生的知识大概就讲到这里啦,博主后续会继续更新更多Linux的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

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

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

相关文章

GPT模型应用丨遥感云大数据在灾害、水体与湿地领域典型案例实践

​ ​ ​ ​ 第一部分 基础实践 一 平台及基础开发平台 GEE平台及典型应用案例介绍&#xff1b; GEE开发环境及常用数据资源介绍&#xff1b; ChatGPT、文心一言等GPT模型介绍 JavaScript基础简介&#xff1b; GEE遥感云重要概念与典型数据分析流程&#xff1b; …

基于单片机的智能鞋柜的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;通过DHT11温湿度采集&#xff1b;通过按键设置逻辑处理&#xff1b;通过LED紫外线消毒&#xff1b;通过继电器控制风扇进行换气除湿&#xff1b;通过继电器控制加热片进行加热&#xff1b;整个电路以5v供电; 电路图 PCB 源代码 #i…

《网络安全标准实践指南》(72页)

导读 摘要&#xff1a;为指导网络数据安全风险评估工作&#xff0c;发现数据安全隐患&#xff0c;防范数据安全风险&#xff0c;依据《中华人民共和国网络安全法》《中华人民共和国数据安全法》《中华人民共和国个人信息保护法》等法律法规&#xff0c;参照数据安全相关国家标…

[QT编程系列-2]:C++图形用户界面编程,QT框架快速入门培训 - 1- 预备知识

目录 概述 1. 前置条件 1.1 C 1.2 图形界面 1.3 图形程序集成开发环境 1.4 图形程序开发框架 1.5 跨平台特性 1.6 QT快速感知 1.6.1 QT的典型应用 1.6.2 QT的特点 1.6.3 QT跨平台集成开发环境 1.6.4 QT是一种UI开发框架 1.6.5 QT的主要函数库 概述 1. 前置条件 学习…

如何在Ubuntu18.04中下载MySQL5.7

检查环境 首先检查自己电脑有没有安装过mysql,输入如下&#xff1a; rpm -qa | grep mysql如果有则清理干净在安装&#xff0c;输入 whereis mysql找到文件夹目录&#xff0c;再把它删除 rpm -e --nodeps mysql-xxx检查系统是否自带mariadb&#xff0c;输入如下检查 rpm -…

Spring6 JdbcTemplate和事务

文章目录 1、JdbcTemplate1.1、简介1.2、准备工作1.3、实现CURD①装配 JdbcTemplate②测试增删改功能③查询数据返回对象④查询数据返回list集合⑤查询返回单个的值 2、声明式事务概念2.1、事务基本概念①什么是事务②事务的特性 2.2、编程式事务2.3、声明式事务 3、基于注解的…

MySQL存储函数和存储过程习题

创建表并插入数据 字段名 数据类型 主键 外键 非空 唯一 自增id INT 是 否 是 是 否name VARCHAR(50) 否 否 是 否 否glass VARCHAR(50) 否 否 是 否 否sch 表内容id name glass1 xiaommg glass 12 xiaojun glass 21、创建一个可以统计…

Vue-cli脚手架

文章目录 前言搭建Vue-Cli脚手架安装npm可能出现的报错及解决办法国内淘宝镜像服务器 全局安装 vue-cli创建 Vue-Cli工程创建 Vue 的基本模板 总结终端打开/关闭操作创建Vue-Cli工程过程 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; Vue CLI是一个基…

【Linux】- Vim 编辑器、开关机、和用户权限管理常用命令

Vim 编辑器、开关机、和用户权限管理常用命令 1.1&#x1f330;vi 和 vim 的基本介绍1.2&#x1f36e;vi 和 vim 常用的三种模式1.3&#x1f320;vim的基本使用2.1&#x1f365;开机、重启2.2&#x1f37c;用户登录注销3.1&#x1f600;用户管理&#xff08;crud&#xff09;3.…

Jvm参数设置-JVM(八)

上篇文章说了逃逸分析和标量&#xff0c;代码实例解析了内存分配先从eden区域开始&#xff0c;当内存不足的时候&#xff0c;才会进入s0和s1&#xff0c;发生yangGC&#xff0c;之后大内存会放入old&#xff0c;因为我们昨天程序运行了一个45M的对象&#xff0c;于是小对象在ed…

数据结构--并查集的进一步优化

数据结构–并查集的进一步优化 Find操作的优化(压缩路径) 压缩路径 − − F i n d 操作&#xff0c;先找到根节点&#xff0c;再将查找路径上所有结点都挂到根结点下 \color{red}压缩路径 -- Find操作&#xff0c;先找到根节点&#xff0c;再将查找路径上所有结点都挂到根结点…

【云原生 • Kubernetes】认识 k8s、k8s 架构、核心概念点介绍

目录 一、Kubernetes 简介 二、Kubernetes 架构 三、Kunbernetes 有哪些核心概念&#xff1f; 1. 集群 Cluster 2. 容器 Container 3. POD 4. 副本集 ReplicaSet 5. 服务 service 6. 发布 Deployment 7. ConfigMap/Secret 8. DaemonSet 9. 核心概念总结 一、Kubern…