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

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://xiahunao.cn/news/3225062.html

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

相关文章

基于与STM32的加湿器之雾化片驱动

基于与STM32的加湿器之雾化片驱动 加湿器是一种由电力驱动&#xff0c;用于增加环境湿度的家用电器。加湿器通过特定的方式&#xff08;如蒸发、超声波振动或加热&#xff09;将水转化为水蒸气&#xff0c;并将这些水蒸气释放到空气中&#xff0c;从而增加空气中的湿度。主要功…

Spin Image(旋转图像)

Spin Image特征描述子原理 Spin Image是Johnson于1999年提出&#xff0c;Lazebnik于2005年完善的基于点云空间分布的特征描述方法&#xff0c;其思想是将一定区域的点云分布转换成二维的Spin Image&#xff0c;然后对场景和模型的Spin Image进行相似性度量。Spin Image方法与通…

怎么制作gif动图,视频制作GIF动画更简单

在社交媒体和网络交流中&#xff0c;GIF动画以其生动活泼的表现形式成为了表达情感、幽默和创意的热门媒介。无论是分享日常趣事&#xff0c;还是制作专业演示&#xff0c;一个恰到好处的GIF动图总能吸引目光&#xff0c;传递信息。 但你知道吗&#xff1f;即使没有专业的设计背…

FastReport 指定sql 和修改 数据库连接地址的 工具类 :FastReportHelper

FastReport 指定sql 和修改 数据库连接地址的 工具类 &#xff1a;FastReportHelper 介绍核心代码&#xff1a;完整代码&#xff1a; 介绍 在FastReport中&#xff0c;经常会遇到需要给 sql 加条件的情况&#xff0c;或者给数据库地址做更换。 &#xff08;废话不多说&#x…

Qt:12.输入类控件(QSpinBox-整数值输入的小部件、QDateEdit、QTimeEdit、QDateTimeEdit- 日期和时间输入的控件)

目录 一、QSpinBox-整数值输入的小部件&#xff1a; 1.1QSpinBox介绍&#xff1a; 1.2属性介绍&#xff1a; 1.3通用属性介绍&#xff1a; 1.4信号介绍&#xff1a; 二、QDateEdit、QTimeEdit、QDateTimeEdit- 日期和时间输入的控件&#xff1a; 2.1QDateEdit、QTimeEdit…

从生物学到机械:人眼如何为机器人视觉系统提供无尽灵感?

人眼激发了相机机制的发展&#xff0c;该机制改善了机器人对周围世界的观察和反应方式。 该摄像头系统由马里兰大学&#xff08;UMD&#xff09;计算机科学家领导的团队开发&#xff0c;模仿人眼用于保持清晰稳定的视力的不自主运动。 该团队对相机的原型设计和测试称为…

第三期书生大模型实战营 第1关 Linux 基础知识

第三期书生大模型实战营 第1关 Linux 基础知识 第三期书生大模型实战营 第1关 Linux 基础知识InternStudio开发机创建SSH密钥配置通过本地客户端连接远程服务器通过本地VSCode连接远程服务器运行一个Python程序总结 第三期书生大模型实战营 第1关 Linux 基础知识 Hello大家好&a…

C++证道之路第三章字符串、向量和数组

一、命名空间的using声明 在C中&#xff0c;命名空间是一种将标识符&#xff08;如变量、函数、类等&#xff09;组织到一个单独的作用域中的机制。当我们在大型项目中工作时&#xff0c;可能会遇到命名冲突的问题&#xff0c;这时命名空间就非常有用。 然而&#xff0c;在使…

使用linux的mail命令发送html格式的邮件

1、关闭本机的sendmail服务或者postfix服务 #执行下面的命令&#xff0c;各位大侠都对号入座吧 #sendmial service sendmail stop chkconfig sendmail off #postfix service postfix stop chkconfig postfix off#再狠一点就直接卸载吧.. yum remove sendmail yum remove postf…

一句话彻底搞懂Java的编译和执行过程

编译和运行可以在不同的计算机上实现。 编译阶段&#xff1a;由Javac编译器将 .Java 的源文件编译为 .class 的字节码文件&#xff1b; 运行阶段&#xff1a; jvm中Java编译器运行 .class 的字节码文件&#xff0c;运行过程中&#xff0c;类加载器从硬盘中找到该字节码文件并…

C语言 | Leetcode C语言题解之第226题翻转二叉树

题目&#xff1a; 题解&#xff1a; struct TreeNode* invertTree(struct TreeNode* root) {if (root NULL) {return NULL;}struct TreeNode* left invertTree(root->left);struct TreeNode* right invertTree(root->right);root->left right;root->right le…

每日Attention学习9——Efficient Channel Attention

模块出处 [CVPR 20] [link] [code] ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks 模块名称 Efficient Channel Attention (ECA) 模块作用 通道注意力 模块结构 模块代码 import torch import torch.nn as nn import torch.nn.functional …

快速掌握 ==== js 正则表达式

git 地址 https://gitee.com/childe-jia/reg-test.git 背景 在日常开发中&#xff0c;我们经常会遇到使用正则表达式的场景&#xff0c;比如一些常见的表单校验&#xff0c;会让你匹配用户输入的手机号或者身份信息是否规范&#xff0c;这就可以用正则表达式去匹配。相信大多数…

记一次java进程异常退出原因排查

最近在对一个Java服务进行压测&#xff0c;但是压测一段时间后&#xff0c;java进程就会自动停止&#xff0c;虽然怀疑可能是内存不足原因导致的&#xff0c;但是从服务日志中去看&#xff0c;并没有OOM的相关报错日志。这就很奇怪了&#xff01;然后就从Java启动参数入手&…

【Python基础】代码如何打包成exe可执行文件

本文收录于 《一起学Python趣味编程》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、安装PyInstaller三、使用PyInstaller打包四、验证打包是否成功五、总结 一、前言 本文介绍如何…

【C语言】continue 关键字详解

当在C语言中使用continue关键字时&#xff0c;它用于控制循环语句的执行流程。与break不同&#xff0c;continue不会终止整个循环&#xff0c;而是终止当前迭代&#xff0c;并立即开始下一次迭代。这种行为使得可以在循环内部根据特定条件跳过某些代码块&#xff0c;从而控制程…

Vue核心 — Vue2响应式原理和核心源码解析(核心中的核心)

一、前置知识 1、Vue 核心概念 Vue 是什么? Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。 Vue 核心特点是什么? 响应式数据绑定:…

2024前端面试真题【JS篇】

DOM DOM&#xff1a;文本对象模型&#xff0c;是HTML和XML文档的编程接口。提供了对文档的结构化的表述&#xff0c;并定义可一种方式可以使从程序中对该结构进行访问&#xff0c;从而改变文档的结构、样式和内容。 DOM操作 创建节点&#xff1a;document.createElement()、do…

AI提示词:打造爆款标题生成器

打开GPT输入以下内容&#xff1a; # Role 爆款标题生成器## Profile - author: 姜小尘 - version: 02 - LLM: Kimi - language: 中文 - description: 利用心理学和市场趋势&#xff0c;生成吸引眼球的自媒体文章标题。## Background 一个吸引人的标题是提升文章点击率和传播力…

压缩感知3——重构算法正交匹配追踪算法

算法流程 问题的实质是&#xff1a;AX Y 求解&#xff08;A是M维&#xff0c;Y是N维且N>>M并且稀疏度K<M&#xff09;明显X有无穷多解&#xff0c;重构过程是M次采样得到的采样值升维的过程。OMP算法的具体步骤&#xff1a;(1)用X表示信号&#xff0c;初始化残差e0 …