【Linux系统化学习】信号概念和信号的产生

目录

信号的概念

从生活中的例子中感知信号

前台进程和后台进程

前台进程

后台进程

操作系统如何知道用户向键盘写入数据了?

进程如何得知自己收到了信号?

信号捕捉

signal函数

Core Dump(核心转储)

信号产生的方式

通过键盘按键产生信号

kill函数

raise函数

硬件异常产生信号

浮点数异常

非法地址异常 

由软件条件产生信号

alarm函数


信号的概念

从生活中的例子中感知信号

  1. 你在网上买了很多件商品,再等待不同商品快递的到来。但即便快递没有到来,你也知道快递来临时,你该怎么处理快递。也就是你能“识别快递”
  2. 当快递员到了你楼下,你也收到快递到来的通知,但是你正在打游戏,需5min之后才能去取快递。那么在在这5min之内,你并没有下去去取快递,但是你是知道有快递到来了。也就是取快递的行为并不是一定要立即执行,可以理解成“在合适的时候去取”。
  3. 在收到通知,再到你拿到快递期间,是有一个时间窗口的,在这段时间,你并没有拿到快递,但是你知道有一个快递已经来了。本质上是你“记住了有一个快递要去取”
  4. 当你时间合适,顺利拿到快递之后,就要开始处理快递了。而处理快递一般方式有三种:1. 执行默认动作(幸福的打开快递,使用商品)2. 执行自定义动作(快递是零食,你要送给你你的女朋友)3. 忽略快递(快递拿上来之后,扔掉床头,继续开一把游戏)
  5. 快递到来的整个过程,对你来讲是异步的,你不能准确断定快递员什么时候给你打电话

通过上面的例子我们可以总结出来一下四点:

  • 信号没有产生的时候,其实我们已经直到怎么处理这个信号了。
  • 信号的到来我们并不清楚具体什么时候,信号的到来对于我正在做的工作是异步产生的。
  • 信号产生了,我们不一定要立即处理它,而是我们在合适的时候处理。
  • 我们有一种能力,可以将已经到来的信号进行暂时保存。

让我们转换视角,将我们看成操作系统中被操作系统管理的进程;在进程运行期间根本不知道操作系统什么时候会给这个进程传递一种信息,当操作系统的信息来临时进程可以选择直接处理这个信息,也可以将信息暂时保存下来。

到此我们可以给信号下个定义信号是一种向目标进程发送通知消息的一种机制

在了解信号的产生之前我们还需要一点预备知识让我们对操作系统的信号机制了解的更全面一点。


前台进程和后台进程

前台进程

当我们循环执行一条输出语句时,执行我们的Linux指令操作系统是没有任何相应的;也就是操作系统没有能力接受用户的输入

后台进程

只需要在运行可执行程序时指令的后面添加一个按位与的位运算符即可成为后台进程。后台进程有能力可以接受用户的输入,当我么输入指令后shell会执行我们的命令。

查看后台进程:

jobs

将后台进程调整为前台进程:

fg number(后台每个进程的任务号)

将前台进程调整为后台进程

ctrl + z
//先对前台进程进行暂停
bg number
//然后在进行调整

总结: 

  1. 前台进程有且只有一个,一般情况下为shell。
  2. 操作系统会自动将shell提到前台或者后台。
  3. 前台进程可以被ctrl+c终止掉。
  4. 前台进程不可以被暂停,如果被暂停该前台进程必须被放到后台。 

操作系统如何知道用户向键盘写入数据了?

操作系统是管理者,键盘、显示器、网卡等这些硬件也是要被操作系统管理起来的。当我们使用键盘进行写入操作时,键盘文件会发生变化;操作系统会将这些输入的数据进行各种处理。但是根据冯诺依曼体系结构外设是不可以和CPU进行打交道的,可以通过其他硬件间接联系。CPU中含有很多针脚,外设通过8259主板和CPU上的针脚关联。每个针脚对应一个外设,当我们键盘进行写入时,高低电平会通过主板让针脚发生“变化”。这样CPU就可以知道键盘进行写入了然后读取数据,对数据进行处理。这样的方式称作中断,引起中断的原因称作中断源。对于CPU上的针脚,操作系统也是需要进行管理的,使用一个函数指针数组;数组中的指针指向该针脚对应外设的读写操作函数。这个函数指针数组被称为断向量表。

因此信号的本质就是使用软件来模拟中断的行为。


进程如何得知自己收到了信号?

前面的文章中我们简单提到过信号系统中总共含有62中信号;其中 1-31为普通信号,34-64为实时信号,且没有0号信号。这篇文章我们只探讨普通信号,不对实时信号做任何解释和介绍。

可以使用kill -l查看系统信号

每个信号都含有一个数字编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有定 义 #define SIGINT 2。

前面的文章我们介绍了每个进程都会被操作系统管理起来,形成一个结构体(PCB)其中含有进程的属性和信息;在这个结构体中就含有一个信号位图,每个比特位代表对应的信号每个比特位对应的内容表示是否收到了信号。当进程收到信号之后,会修改这个信号位图表示收到了某中信号。


信号捕捉

上面提到每个信号都有编号和宏定义,当进程收到某种信号时会调用系统默认的方法;Linux操作系统支持我们使用函数将默认方法改写。

signal函数

//头文件
#include<signal.h>
//函数名称
signal(signo,(void)(*)(int))
  • 第一个参数表示我们要对哪个信号进行捕捉。
  • 第二个参数是一个参数为整形的函数指针,指向我们重写的函数;这个函数的参数也为我们的第一个参数。

注意:对于9号进程来说是不可以被重写函数的。


Core Dump(核心转储)

首先解释什么是Core Dump。当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部 保存到磁盘上,文件名通常是core,这叫做Core Dump。进程异常终止通常是因为有Bug,比如非法内存访问导致段错误,事后可以用调试器检查core文件以查清错误原因,这叫做Post-mortem Debug(事后调试)。一个进程允许产生多大的core文件取决于进程的Resource Limit(这个信息保存 在PCB中)。默认是不允许产生core文件的,因为core文件中可能包含用户密码等敏感信息,不安全。在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件。 首先用ulimit命令改变Shell进程的Resource Limit,允许core文件最大为1024K: $ ulimit -c 1024。

#include<iostream>
using namespace std;
int main()
{int a=10;a/=0;return 0;
}

使用指令修改限制,允许产生core文件;专门制造一个浮点数异常编译并运行后会产生一个和本进程id相关的core文件;我们可以发现这个文件是非常大的,程序运行时如果出现这类异常会将我们的磁盘写满,造成无法进行修改这也是为什么系统默认不允许产生core文件。


信号产生的方式

通过键盘按键产生信号

通过键盘进行信号的产生就像我们上面使用键盘输入crtl +c可以终止一个进程,当这个键盘输入组合键时会产生一个硬件中断,被操作系统获取,解释成为2号信号,发送给目标前台进程。进程会修改自己PCB中的信号位图,表示已经收到信号。

前台进程因为接收到引号,直接对信号进行处理,进而终止进程。

此外常用的组合键含有:ctrl + z 默认暂停进程 ctrl + \ 默认退出进程

通过系统调用/指令产生信号

kill函数

//头文件
#include<sys/types.h>
#include<signal.h>
//函数
int kill(pid_t pid, int sig)

参数说明:

  • pid:表示进程的pid,代表向哪一个进程发送。
  • sig:表示发送信号的编号。 
#include<iostream>2 #include<unistd.h>3 #include<signal.h>4 #include<sys/types.h>                                              5 using namespace std;                                                  10 int main()                           11 {                                    12     cout<<"wait 2 signal"<<endl;     13     sleep(2);                        14     kill(getpid(),9);                15     cout<<"WTF"<<endl; return 0;}

上面的代码演示了使用kill函数给自身进程产生了9号信号,并由操作系统发送成功;也可以通过另一个进程给一个指定的进程发送指定的信号。

raise函数

//头文件
#include<signal.h>
//函数
int raise(int sig);

参数说明:

  • sig:代表信号编号。
  • raise专门用来给自己发送指定的信号的。 
 #include<iostream>2 #include<unistd.h>3 #include<signal.h>4 #include<sys/types.h>5 using namespace std;10 int main()11 {12     cout<<"wait signal"<<endl;13     raise(9);    reutrn 0;}                                                  

硬件异常产生信号

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

浮点数异常

#include<iostream>
using namespace std;
int main()
{int a=10;a/=0;return 0;
}

非法地址异常 

#include<iostream>
using namespace std;
int main()
{int* a=NULL;*a=100;return 0;
}

 

由软件条件产生信号

在之前管道的文章,匿名管道如果读端关闭,写端一直写入;操作系统就会发送SIGPIPE(13)号信号终止目标进程。SIGPIPE就是一种由软件条件产生的信号。

alarm函数

//头文件
#include <unistd.h>
//函数
unsigned int alarm(unsigned int seconds);

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

这个函数的返回值是0或者是以前设定的闹钟时间还余下的秒数。打个比方,某人要小睡一觉,设定闹钟为30分钟之后响,20分钟后被人吵醒了,还想多睡一会儿,于是重新设定闹钟为15分钟之后响,“以前设定的闹钟时间还余下的时间”就是10分钟。如果seconds值为0,表示取消以前设定的闹钟,函数的返回值仍然是以前设定的闹钟时间还余下的秒数。

#include<iostream>
#include<unistd.h>
int cnt = 0;
int main()
{alarm(1);while(true){cnt++;cout<<cnt<<endl;}return 0;
}


今天对Linux下信号的产生的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!!  

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

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

相关文章

黑马c++ STL部分 笔记(2) string容器

char*是指针 string是类&#xff0c;类内部封装了char*&#xff0c;管理这个字符串&#xff0c;是一个char*型的容器 函数&#xff1a;find,copy,delete,replace,insert等 1.构造string // string的构造方式&#xff1a; // 1 string() 创建一个空字符串 string str // 2 s…

LeetCode 刷题 [C++] 第102题.二叉树的层序遍历

题目描述 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 题目分析 题目中要求层序遍历二叉树&#xff0c;即二叉树的广度优先搜索(BFS)。BFS一般使用队列的先入先出特性实现&#…

react倒计时功能

目录 类组件写法 函数组件写法&#xff1a; demo: 手机获取验证码登录&#xff08;验证码60秒倒计时&#xff09; react倒计时5 秒 React中的倒计时可以通过使用setInterval()函数来实现。下面是一个示例代码&#xff1a; 类组件写法 import React from react; import { But…

【Docker】狂神说

图片后补 官网&#xff1a; https://www.docker.com/ Docker概述 Docker为什么出现 原因&#xff1a;环境配置不能跨平台 方案 传统方式&#xff1a;jar&#xff08;开发人员&#xff09; 部署&#xff08;运维人员&#xff09; 解决方式&#xff1a;开发打包上线一套流程 …

推荐几个css+js特效网站

CodePen&#xff08;https://codepen.io/&#xff09;&#xff1a;CodePen不仅仅是一个CSS编辑器&#xff0c;它也是一个广受欢迎的JavaScript特效展示平台。你可以在CodePen上浏览和搜索其他开发者创建的各种JavaScript特效&#xff0c;从而获得灵感和学习如何实现不同的效果。…

【算法集训】基础算法:基础排序 - 选择排序

从上一学期期末考完之后就鸽了&#xff0c;真的惭愧&#xff0c;还想着期末考完就开始呢&#xff0c;结果考驾照完了后又有学校项目要忙活。终于是拖到开学了哈哈&#xff0c;虽然现在事情也比较多&#xff0c;但是总归是要开始的&#xff0c;不然马上就要拖延症晚期了&#xf…

设计模式:结构型模式

1. 适配器模式 (Adapter Pattern) 适配器模式是一种结构型设计模式&#xff0c;旨在将一个类的接口转换成客户端所期待的另一个接口&#xff0c;从而使原本由于接口不兼容而无法一起工作的类能够协同工作。适配器模式通常用于需要复用现有类但其接口与要求不匹配的情况。 1.1…

Qt SQLite的创建和使用

重点&#xff1a; 1.SQLite创建数据库内容方法 链接&#xff1a;SQLite Expert Personal的简单使用-CSDN博客 2.和数据库进行链接方法 QSqlDatabase DB; //数据库连接bool MainWindow::openDatabase(QString aFile) {DBQSqlDatabase::addDatabase("QSQLITE"); /…

使用uniapp开发时自定义tabbar

预览图&#xff1a; 一、配置page.jsong中的tabbar&#xff08;这一步是必须的&#xff0c;因为我们在使用uni.switchTab()时必须要用到&#xff09; "tabBar": {"list": [{"pagePath": "pages/index/index","iconPath": &…

java回顾总结--代理模式

目录 一、代理模式1.1 静态代理示例 1.2 动态代理示例 二、总结 一、代理模式 1.1 静态代理 代理模式给某一个对象提供一个代理对象&#xff0c;并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。比如你按照小卡片上的电话打过去寻求服务&#…

C# 学习第四弹——字符串

一、char类型的使用 字符使用单引号&#xff0c;单个字符 转义字符是一种特殊的字符变量&#xff0c;以反斜线开头&#xff0c;后跟一个或多个字符。 输出多级目录可以使用 二、字符串的声明和初始化 1、引用字符串常量 引用字符串常量初始化——字符使用单引号&#xff0…

加密与安全_探索常用编码算法

文章目录 概述什么是编码编码分类ASCII码 &#xff08;最多只能有128个字符&#xff09;Unicode &#xff08;用于表示世界上几乎所有的文字和符号&#xff09;URL编码 &#xff08;解决服务器只能识别ASCII字符的问题&#xff09;实现&#xff1a;编码_URLEncoder实现&#xf…

K8S常用kubectl命令汇总(持续更新中)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

【Prometheus】基于Altertmanager发送告警到多个接收方、监控各种服务、pushgateway

基于Altertmanager发送报警到多个接收方 一、配置alertmanager-发送告警到qq邮箱1.1、告警流程1.2、告警设置【1】邮箱配置【2】告警规则配置【3】 部署prometheus【4】部署service 二、配置alertmanager-发送告警到钉钉三、配置alertmanager-发送告警到企业微信3.1、注册企业微…

量子算法入门—4.量子比特与量子门(1)

1.量子比特 经典比特和量子比特 经典比特只有0、1两种取值&#xff0c;非黑即白&#xff0c;有n位即 2 n 2^n 2n种可能量子比特使用0、1的量子态描述量子比特的状态&#xff0c;可以通过线性组合形成新的量子态&#xff0c;就像光谱可以调节成分 引入线代记法&#xff0c;0、…

ARK:《BIG IDEAS 2024》

Cathie Wood所带领的方舟投资&#xff08;ARK&#xff09;发布了年度重磅研究报告《BIG IDEAS 2024》&#xff0c;该报告指出人工智能、公共区块链、多组学测序、能源存储和机器人技术这五大板块的融合将带来全球经济活动的改变。 这五个创新平台正在融合并定义这个技术时代&am…

92. 递归实现指数型枚举 刷题笔记

思路 dfs 考虑选或者不选每个位置 用0表示未考虑 1表示选 2表示不选 用u表示搜索状态 u>n时 已经搜到底层了 需要输出当前方案 遍历 如果选了则输出 #include<iostream> using namespace std; int n; const int N16; int st[N]; void dfs(int u){ //u来记…

Git自动忽略dll文件的问题

检查了半天发现是sourcetreee的全局忽略文件导致&#xff0c; 从里面删除dll即可。 我是干脆直接删了全局忽略&#xff0c;太恶心了&#xff0c;如下&#xff1a; #ignore thumbnails created by windows Thumbs.db #Ignore files build by Visual Studio *.exe .vsconfig .s…

fastAdmin表格列表的功能

更多文章&#xff0c;请关注&#xff1a;fastAdmin后台功能详解 | 夜空中最亮的星 FastAdmin是一款基于ThinkPHP5Bootstrap的极速后台开发框架。优点见开发文档 介绍 - FastAdmin框架文档 - FastAdmin开发文档 在这里上传几张优秀的快速入门图: 一张图解析FastAdmin中的表格列…

Linux网络编程(四-TCP协议)

目录 一、TCP概念 二、TCP的首部格式 三、TCP可靠传输机制 3.1 确认应答机制 3.2 超时重传机制 3.3 连接管理 3.3.1 三次握手 3.3.2 四次挥手 3.4 流量控制 3.5 拥塞控制 四、TCP效率机制 4.1 滑动窗口 4.2 重发控制 4.3 延迟应答 4.4 捎带应答 五、TCP的…