操作系统:信号究竟是什么?如何产生?

OS信号

  • 一、信号的概念
  • 二、信号的产生
  • 1)终端按键产生信号
    • 1、 前台进程、后台进程
    • 2、验证终端按键是否产生信号
  • 2)调用系统函数向进程发信号
  • 3)硬件异常产生信号
    • 1、浮点数溢出,CPU产生信号
    • 2 浮点数溢出,产生信号原理
    • 3. 空指针解引用错误,MMU产生信号原理
  • 4)软件异常产生信号

一、信号的概念

信号是一种向目标进程发送信息,异步通知的一种方式,属于软中断。本质上是用软件来模拟中断行为!

 在生活中存在很多信号,诸如红绿灯、闹钟铃声、古代狼烟、防空警报等等。以红绿灯为例,我们是如何认识红绿灯信号的。根本原因在于我们在小时候就已经有人提前告诉你如何去识别它、对应的灯亮了意味这什么,要做什么!

 同理,在操作系统中已经提前内置了信号信息。我们通过kill -l查看:

在这里插入图片描述

  • 每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到。其中 1~31为普通信号,43~64为实时信号(不关心),没有32、33号信号!这些信号各自在什么条件下产生,默认的处理动作是什么,在signal(7)中都有详细说明: man 7 signal

 在操作系统中,信号还没有产生之前,进程就能识别它(数字代号或宏),如何处理。信号的到来,我们并不清楚是什么时候,所以信号相对进程来说是异步的。信号产生后,进程不一定立即处理它,而是在合适的时候进程处理。所以我们需要将已经到来的信号进行保存

  • 所以信号如何产生?操作系统如何保存信息?

二、信号的产生

 在操作系统中,产生信号有4种方式:终端按键产生、系统调用产生、硬件异常产生、软件条件产生!

1)终端按键产生信号

 下面通过终端按键向前台进程和后台进程发送信号为例!

1、 前台进程、后台进程

 下面我们创建一个process.cc源文件,让其死循环输出信息。

#include <iostream>
#include <unistd.h>int main()
{int cnt = 0;while(true){std::cout << "running ..." << ++cnt << std::endl;sleep(1);}return 0;
}
  1. 我们编译运行后,产生一个前台进程。我们可以在终端输入ctrl c发送2号信号来终止前台进程!

请添加图片描述
 我们在键盘上按下ctrl z后,会产生硬件中断。操作系统会识别到硬件数据就绪,此时操作系统读键盘上的数据,发送给目标进程。前台进程因为收到2号信号,进而引起信号退出!!

  1. 我们也可以通过ctrl z发送20号信号暂停前台进程!但由于前台进程不能被暂停,否则键盘将失效。此时当前被暂停的前台进程后转化为后台进程。shell外壳进程快速从后台切换为前台进程。

 下面我们将前台进程输入重定向到log.txt,死循环打印消息。然后ctrl z发送20号信号,此时前台进程会变为后台进程。具体效果如下:

请添加图片描述

 我们发现ctrl z向目标进程发送20号信号后,前台进程变为后台进程,并且被暂停!

  1. jobs指令可以查看当前系统中的后台进程。
  2. bg 指令+ 后台进程编号可以重新启动后台进程。fg 指令+ 后台进程编号可以将后台进程提到前台,变为前台进程!
  3. 前台进程只能有一个(键盘只有一个),后台进程可以有多个。两者本质区别在于前台进程可以接收用户输入,后台不行。shell进程比较特殊,不会被ctrl c杀掉。并且根据具体情况,Os会自动将shell提到前台或后台!!

2、验证终端按键是否产生信号

 上述我们通过终端按键让进程产生一系列行为。当ctrl c真的向目标进程发送了2号信号吗?ctrl z真的向目标进程发送了20号信号吗?我们需要进一步验证!

 操作系统提供了一个signal系统调用即可,可以自定义捕捉信号。

 #include <signal.h>//函数原型如下,signal()第二个参数用于自定义捕捉信号typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);

下面我们以自定义捕捉2号信号,分别通过终端ctrl c和用户主动发送2号信号,对比进程行为!!

【源代码如下】:自定义捕捉2号信号,让进程受到2号信号退出时,打印一段消息!!

#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>void handler(int signo)
{std::cout << "自定义捕捉信号: " << signo << std::endl;exit(0);
}int main()
{std::cout << "pid: " << getpid() << std::endl;//自定义捕捉2号信号,signal()会将待捕捉信号种类数字传给handler()signal(2, handler);int cnt = 0;while(true){std::cout << "running ..." << ++cnt << std::endl;sleep(1);}return 0;
}

【终端ctrl c效果】:

请添加图片描述

【发送2号信号效果】:
请添加图片描述

  • 我们发现两者行为一直,系统都受到了2号信号。进一步验证终端输入可以发送信号!!

2)调用系统函数向进程发信号

 操作系统提供了系统调用接口kill,用来向指定进程发送特定信号!

 //函数原型#include <sys/types.h>#include <signal.h>int kill(pid_t pid, int sig);//发送成功,返回0;否则返回-1

【实例】:进程打印3次消息后,通过系统调用接口发送2号信号

#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>void handler(int signo)
{std::cout << "自定义捕捉信号: " << signo << std::endl;exit(0);
}int main()
{int count = 3, cnt = 0;signal(2, handler);//自定义捕捉2号信号while(true){std::cout << "running ..." << ++cnt << std::endl;if(--count == 0)kill(getpid(), 2);sleep(1);}return 0;
}

【运行结果】:
请添加图片描述

  1. kill命令是调用kill函数实现的。kill函数可以给一个指定的进程发送指定的信号。
  2. raise函数可以给当前进程发送指定的信号(自己给自己发信号)。
#include <signal.h>
int raise(int signo);
//是成功返回0,错误返回-1。
  1. abort函数使当前进程接收到信号而异常终止。
#include <stdlib.h>
void abort(void);
//就像exit函数一样,abort函数总是会成功的,所以没有返回值。

3)硬件异常产生信号

 下面以浮点数溢出和空指针解非法解引用错误为例

1、浮点数溢出,CPU产生信号

 我们知道除式中,除数为0是非法的。此时CUP硬件会发送8号信号,表示浮点数异常Floating point exception。我们先来看看相关现象,代码如下:(我们特意让进程一直被运行,并且8号信号自定义捕捉。进程收到8号信号时不退出

#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>void handler(int signo)
{std::cout << "自定义捕捉信号: " << signo << std::endl;sleep(1);
}int main()
{std::cout << "pid: " << getpid() << std::endl;signal(8, handler);int x = 10;x /= 0;while(true){}return 0;
}

【运行结果】:

请添加图片描述
 我们观察到进程确实收到了8号信号。

2 浮点数溢出,产生信号原理

 在CPU中存在许多寄存器,其中存在一个名为status的状态寄存器,其中存在一个标志位用来保存最近一次运算结果是否发送溢出!!
 加上我们CPU寄存器eax中保存10,ebx寄存器中保存0。10/0,本质上是除一个无限小的数,导致结果无限大,发生溢出。此时操作系统会识别到该信息,然后立即将当前进程从CPU上剥离,添加到某种异常处理队列。

 此时操作系统会将该异常解释位kill(targetprocess, signo)。然后保存到进程PCB中!当异常处理完后,会被CPU再次调度运行,执行后续代码!

 但此时我们自定义捕捉了8号信号,没有让进程退出,会一直循环上述过程。
在这里插入图片描述

3. 空指针解引用错误,MMU产生信号原理

 MMU(内存管理单元),它是一种负责处理中央处理器(CPU)的内存访问请求的计算机硬件,现如今一般别集成到CPU上。 它的功能包括虚拟地址到物理地址的转换(即虚拟内存管理)、内存保护等!

 对空指针进行非法解引用,即试图对0号地址进行写入。但此时页表中没有建立相关映射,此时MMU进程虚拟地址向物理地址转化时发送失败,MMU报错,相关标志位改变。该变化会被OS识别后向目标进程写信号!!

4)软件异常产生信号

 对于管道,比如匿名管道等存在同步机制的管道。当读端关闭,此时管道写端也会关闭退出。这就是一种典型的软件异常。当管道写端关闭,写端进行写入时会触发 SIGPIPE14信号。进而关闭读端退出!

 下面我i们以alarm函数为例,测试软件异常。
调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动作是终止当前进程。

//函数原型#include <unistd.h>unsigned int alarm(unsigned int seconds);
//返回值是0或者是以前设定的闹钟时间还余下的秒数

 下面我们设置一个3秒的闹钟,程序运行后闹钟醒来发送14号信号!

#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>int cnt = 0;void handler(int signo)
{//下面注释代码:我们可以主动发送14号信号,历史闹钟剩余时间,并取消历史闹钟//int n = alarm(0);//取消历史闹钟,如果存在返回剩余时间//std::cout << "result:" << n << std::endl;std::cout << "自定义捕捉信号: " << signo << "alarm" << std::endl;exit(0);
}int main()
{std::cout << "pid: " << getpid() << std::endl;signal(14, handler);alarm(30);while (true){sleep(1);}return 0;
}

【运行结果】:
请添加图片描述

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

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

相关文章

神经网络构成、优化、常用函数+激活函数

Iris分类 数据集介绍&#xff0c;共有数据150组&#xff0c;每组包括长宽等4个输入特征&#xff0c;同时给出输入特征对应的Iris类别&#xff0c;分别用0&#xff0c;1&#xff0c;2表示。 从sklearn包datasets读入数据集。 from sklearn import darasets from pandas impor…

【密码学】分组密码概述

一、分组密码的定义 分组密码和流密码都是对称密码体制。 流密码&#xff1a;是将明文视为连续的比特流&#xff0c;对每个比特或字节进行实时加密&#xff0c;而不将其分割成固定的块。流密码适用于加密实时数据流&#xff0c;如网络通信。分组密码&#xff1a;是将明文数据…

GuLi商城-商品服务-API-品牌管理-OSS获取服务端签名

新建第三方服务: 引入common 把common中oss的依赖都拿到第三方服务中来 配置文件: 加上nacos注解:<

windows USB 设备驱动开发-USB带宽

本文讨论如何仔细管理 USB 带宽的指导。 每个 USB 客户端驱动程序都有责任最大程度地减少其使用的 USB 带宽&#xff0c;并尽快将未使用的带宽返回到可用带宽池。 在这里&#xff0c;我们认为USB 2.0 的速度是480Mbps、12Mbps、1.5Mbps&#xff0c;这分别对应高速、全速、低速…

【QML之·基础语法概述】

系列文章目录 文章目录 前言一、QML基础语法二、属性三、脚本四、核心元素类型4.1 元素可以分为视觉元素和非视觉元素。4.2 Item4.2.1 几何属性(Geometry&#xff09;:4.2.2 布局处理:4.2.3 键处理&#xff1a;4.2.4 变换4.2.5 视觉4.2.6 状态定义 4.3 Rectangle4.3.1 颜色 4.4…

《植物大战僵尸杂交版》2.2版本:全新内容与下载指南

《植物大战僵尸杂交版》2.2版本已经火热更新&#xff0c;带来了一系列令人兴奋的新玩法和调整&#xff0c;为这款经典的塔防游戏注入了新的活力。如果你是《植物大战僵尸》系列的忠实粉丝&#xff0c;那么这个版本绝对值得你一探究竟。 2.2版本更新亮点 新增看星星玩法 这个新…

宏碁F5-572G-59K3笔记本笔记本电脑拆机清灰教程(详解)

1. 前言 我的笔记本开机比较慢&#xff0c;没有固态&#xff0c;听说最近固态比较便宜&#xff0c;就想入手一个&#xff0c;于是拆笔记本看一下有没有可以安的装位置。&#xff08;友情提示&#xff0c;在拆机之前记得洗手并擦干&#xff0c;以防静电损坏电源器件&#xff09…

ChatTTS使用

ChatTTS是一款适用于日常对话的生成式语音模型。 克隆仓库 git clone https://github.com/2noise/ChatTTS cd ChatTTS 使用 conda 安装 conda create -n chattts conda activate chattts pip install -r requirements.txt 安装完成后运行 下载模型并运行 python exampl…

Python酷库之旅-第三方库Pandas(013)

目录 一、用法精讲 31、pandas.read_feather函数 31-1、语法 31-2、参数 31-3、功能 31-4、返回值 31-5、说明 31-6、用法 31-6-1、数据准备 31-6-2、代码示例 31-6-3、结果输出 32、pandas.DataFrame.to_feather函数 32-1、语法 32-2、参数 32-3、功能 32-4、…

【计算机毕业设计】基于Springboot的IT技术交流和分享平台【源码+lw+部署文档】

包含论文源码的压缩包较大&#xff0c;请私信或者加我的绿色小软件获取 免责声明&#xff1a;资料部分来源于合法的互联网渠道收集和整理&#xff0c;部分自己学习积累成果&#xff0c;供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者…

14-56 剑和诗人30 - IaC、PaC 和 OaC 在云成功中的作用

介绍 随着各大企业在 2024 年加速采用云计算&#xff0c;基础设施即代码 (IaC)、策略即代码 (PaC) 和优化即代码 (OaC) 已成为成功实现云迁移、IT 现代化和业务转型的关键功能。 让我在云计划的背景下全面了解这些代码功能的当前状态。我们将研究现代云基础设施趋势、IaC、Pa…

MATLAB备赛资源库(1)建模指令

一、介绍 MATLAB&#xff08;Matrix Laboratory&#xff09;是一种强大的数值计算环境和编程语言&#xff0c;特别设计用于科学计算、数据分析和工程应用。 二、使用 数学建模使用MATLAB通常涉及以下几个方面&#xff1a; 1. **数据处理与预处理**&#xff1a; - 导入和处理…

MacOS如何切换shell类型

切换 shell 类型 如果你想在不同的 shell 之间切换&#xff0c;以探索它们的不同之处&#xff0c;或者因为你知道自己需要其中的一个或另一个&#xff0c;可以使用如下命令&#xff1a; 切换到 bash chsh -s $(which bash)切换到 zsh chsh -s $(which zsh)$()语法的作用是运…

VSCode无法连接网络安装插件-手动安装插件

手动安装插件&#xff1a; 你可以尝试从 Visual Studio Code Marketplace 下载 .vsix 文件&#xff0c;然后在VSCode中手动安装。 手动安装的步骤如下&#xff1a; 1.访问插件页面&#xff0c;下载 .vsix 文件。 Extensions for Visual Studio family of products | Visual S…

CSS【详解】层叠 z-index (含 z-index 的层叠规则,不同样式的层叠效果)

仅对已定位的元素&#xff08; position:relative&#xff0c;position:absolute&#xff0c;position:fixed &#xff09;有效&#xff0c;默认值为0&#xff0c;可以为负值。 z-index 的层叠规则 z-index 值从小到大层叠 兄弟元素 z-index 值相同时&#xff0c;后面的元素在…

MySQL架构你了解多少?

MySQL是一个服务器-客户端应用&#xff0c;MySQL8.0服务器是由连接池、服务管理工具和公共组件、NoSQL接口、SQL接口、解析器、优化器、缓存、存储引擎、文件系统组成。MySQL还为各种编程语言提供了一套用于外部程序访问服务器的连接器。整体架构图如下所示: MySQLConnectors:为…

文件操作和IO流(Java版)

前言 我们无时无刻不在操作文件。可以说&#xff0c;我们在电脑上能看到的图片、视频、音频、文档都是一个又一个的文件&#xff0c;我们需要从文件中读取我们需要的数据&#xff0c;将数据运算后也需要将结果写入文件中长期保存。可见文件的重要性&#xff0c;今天我们就来简…

windows实现Grafana+Loki+loki4j轻量级日志系统,告别沉重的ELK

文章目录 Loki下载Grafana下载安装Loki添加Loki数据源springboot日志推送 Loki下载 下载地址&#xff1a;https://github.com/grafana/loki/releases/ 找到loki-windows-amd64.exe.zip点击开始下载&#xff0c;我这里下载的2.9.9版本 Grafana下载 下载地址&#xff1a;http…

Hi3861 OpenHarmony嵌入式应用入门--MQTT

MQTT 是机器对机器(M2M)/物联网(IoT)连接协议。它被设计为一个极其轻量级的发布/订阅消息传输 协议。对于需要较小代码占用空间和/或网络带宽非常宝贵的远程连接非常有用&#xff0c;是专为受限设备和低带宽、 高延迟或不可靠的网络而设计。这些原则也使该协议成为新兴的“机器…

“Numpy数据分析与挖掘:高效学习重点技能“

目录 # 开篇 # 补充 zeros & ones eye 1. numpy数组的创建 1.1 array 1.2 range 1.3 arange 1.4 常见的数据类型 1.5 astype 1.6 random.random() & round 2. numpy数组计算和数组计算 2.1 reshape 2.2 shape 2.3 将一维数组变成多维数组 2.4 指定一维…