Linux:进程信号的概念与产生原理

文章目录

  • 信号的概念
  • 实践信号
    • 关于前台和后台进程的操作
  • 操作系统与外设
  • 信号的产生
  • signal系统调用

前面的篇章结束了信号量的话题,那么接下来引入的是信号的话题,信号和信号量之间没有任何关系,只是名字比较像

信号的概念

在生活中存在各种各样的信号,例如有红绿灯这样的存在,而进程信号和生活中的信号其实是比较像的,为什么有红灯停绿灯行这样的概念,其实就是因为作为人从小就被指导有这样的观念,因此对应到进程信号中,有下面的几个结论:

  1. 当信号还没有产生的时候,其实进程就已经知道如何应对这个信号了,这是操作系统在设计的时候就已经被设计好的理念,所以在内核中存在这样的设计:

在这里插入图片描述

上述的这些信号就是在操作系统内部已经设计好的内容,当某个进程得到了这样某种信号,就会对对应的信号做出反应,就如同当人遇到绿灯会行驶,遇到红灯会停止一样的道理

  1. 信号的到来,进程并不清楚具体什么时候来,信号的到来和当前进程的逻辑是异步产生的
  2. 信号产生后,进程并不一定要立即处理它,而是在一个合适的时机进行处理,这也就意味着进程必须要对于即将来临的信号有一定的存储能力,以便于在外来需要对该信号处理的时候可以找到这个信号并进行处理

异步的概念

在第二条结论中提及到了异步的概念,因此这里对于异步进行一些解释

同步和异步是一组概念,同步概念的引出是在管道中引出的,管道的执行逻辑是具有一定的顺序性,产生顺序性的本质是让两个进程相互知道彼此的两个进程,感受到对应进程的存在,这也就是为什么管道在写端写满后,如果读端不读,写端就不会写的原因,这就是因为两个进程之间建立了一定的相关性,两个进程之间是会相互影响的,而对于异步来说,就是同步的相反点,当进程a向某个位置输出信息时,进程a没有因为其他外界的原因导致停止对于某个位置信息的输出,而是在一直输出,那么这个过程就称作是异步

信号的本质是一种向目标进程发送通知消息的一种机制

实践信号

#include <iostream>
#include <unistd.h>
using namespace std;

int main()
{
    while (true)
    {
        cout << "it is a process, pid:" << getpid() << endl;
        sleep(1);
    }
    return 0;
}

运行上述结果

在这里插入图片描述

此时会发现的现象是,运行的任何命令都没有效果,此时运行kill命令就可以对其进行终止了:

在这里插入图片描述
此时进程终止,并且以前的命令也都显示出来了

下面对上述的现象做出解释

进程在运行的过程中,通常有两种模式,一种是前台模式,运行方式是

./process

一种是后台模式,运行方式是

./process &

这是对于一个进程的两种运行方式,其中后台程序一般是执行一些耗时比较长的任务,就可以使用后台进行启动,并且不会占用前台的操作

对于Linux系统来说,前台程序执行后再进行输入命令就无效了,为什么?因为shell本身也是一个进程,如果把一个进程放到了前台,那么就相当于把shell放到了后台,shell放到了后台,自然就不能对用户的命令进行解释了,因此区分一个进程是用前台启动的还是后台启动的,就看能不能从键盘上接受用户的输入,这也是最直接的方法

关于前台和后台进程的操作

[test@VM-16-11-centos signal]$ ./process >> log1.txt &
[1] 11861
[test@VM-16-11-centos signal]$ ll
total 24
-rw-rw-r-- 1 test test  351 Jan 30 16:13 log1.txt
-rw-rw-r-- 1 test test   79 Jan 30 12:58 Makefile
-rwxrwxr-x 1 test test 9176 Jan 30 12:58 process
-rw-rw-r-- 1 test test  198 Jan 30 12:55 Process.cc
[test@VM-16-11-centos signal]$ jobs
[1]+  Running                 ./process >> log1.txt &
[test@VM-16-11-centos signal]$ fg 1
./process >> log1.txt
ll
pwd
^Z
[1]+  Stopped                 ./process >> log1.txt
[test@VM-16-11-centos signal]$ bg 1
[1]+ ./process >> log1.txt &
[test@VM-16-11-centos signal]$ jobs
[1]+  Running                 ./process >> log1.txt &

在这里插入图片描述

将一个进程从后台提到前台

fg number

将一个进程从前台放到后台,自动沉睡

ctrl+z

将一个后台程序唤醒

bg number

查看当前运行的后台进程

jobs

操作系统与外设

如果谈到进程信号,就需要引入中断的概念,但是对于中断的概念来说,更需要提及的是这样的问题

操作系统是硬件的管理者,所以硬件上的变化操作系统应该知道并且接收,例如鼠标点击了哪里,键盘按下了哪个键,这些操作系统都要知道,只有知道了键盘按下的数据,才能根据冯诺依曼体系,利用键盘驱动把键盘上的数据拷贝到操作系统中对应键盘的文件缓冲区中,上层就可以通过文件描述符把对应的数据读取上来,所以scanf就能读取到对应的数据了

问题是:操作系统怎么知道键盘被按下了?

由冯诺依曼体系可以知道,计算机结构中有输入单元,也有输出单元,有内存CPU外设这些信息,那么操作系统是如何知道外设中的数据就绪了呢?难道是让操作系统隔一段时间就去检测一下外设中的输入信息吗?结合实际生活的经验以及操作系统对于效率的控制就能知道,这是绝对不可能的,所以一定是让硬件来告诉操作系统

操作系统最初在进行设定的时候,就要求CPU和外设要取得同步,能够让CPU知道关于外设上的各种信息,所以引入了一门新的技术叫做中断技术,关于中断技术,就要先清楚CPU本身的结构,CPU内部有运算器做数据处理,也有控制器进行设备的控制,那么也就意味着CPU必定要和设备直接或间接的相连,所以CPU就会提供一个一个的针脚,这个针脚是有编号的,针脚会与电脑中的主板相连,而主板上的硬件电路是和外设相连,所以在冯诺依曼体系中,CPU之和内存进行数据交互,就是因为外设太慢了,但是实际上CPU一定是会和外设有关联的,只不过不是进行直接的数据交互,那在计算机中,主板就担任了关联的角色,在主板上有各种各样的硬件电路,这些硬件电路就和CPU上的针脚相连,换句话说,当电脑上插入一个新的外设设备后,实际上就和电脑连接完毕了,此时键盘上发送的消息,CPU就能知道,发送的信息就叫做中断信息

对于中断信息这个概念来说,中断体现在把光电信号就叫做中断,换句话说,对应在电脑中的每一个外设与CPU本身都可以进行高低电平的信息交互,外设和CPU硬件是可以间接相连的,未来也能够进行数据的拷贝,不光如此,键盘在触发的时候会产生出很多的光电信号,这些光电信号的强弱就会被CPU识别到,CPU中的各种各样的寄存器就能对这些光电信号进行识别,识别的结果其实就是说某一种数据被放到了计算机中,这样就被操作系统读取到了,这样也就把硬件的行为信息转换成了软件的信息

经过上面的这一系列过程,就把数据从硬件转换到软件了,软硬件结合的本质就是通过寄存器或者内存中的数据来进行软硬件的数据结合

关于8259板

电脑上可以插入很多的电子设备,可能是键盘网卡这样对于操作系统来说有用的硬件设备,也可能是一个普通的风扇这样,仅仅是需要供电的设备,那么操作系统对于每个这样的设备都要进行链接吗?答案是否定的,在CPU和硬件之间会有一个电路板,叫做8259板,和电脑相连的所有设备,都会通过这个电路板再传递给CPU,而这个电路板的作用就是可以把有效的信息进行转换,传递给CPU中

所以得出的一个结论是,外设可以间接的向CPU特定的针脚中发送信息,表示自己的数据已经就绪了,而CPU中每一个针脚都会有一个对应的编号,这个编号就叫做中断号,因此在计算机中,每一个设备都会分配不同的中断号,当这个设备发生中断后,就能识别到这个设备的信息已经就绪了,那CPU就能通过这些信息拿到键盘上对应的中断号,拿到中断号之后,为了能够更快的对这些外设做出响应,在操作系统的内部会提供一张表,这个表中是一个函数指针数组,存储的是一个一个的指针,而这些指针指向的内容就是特定硬件的读取方法,当外设启动的时候,就会通过这张表形成对应硬件就绪后的读取方法,当中断号传递来之后,就借助这个数组索引到需要的内容,进而读取到这个设备想要传递来的数据信息。这张表叫做中断向量表,这张表在操作系统启动的时候,就要创建出的一张表。这样就保持了操作系统高效的特点,同时也能读取到各个设备上的消息

当用户摁键盘的时候,键盘就会基于中断来进行驱动,所以就会通过硬件告知CPU,进而通过操作系统把中断号提取出来,再从中断向量表中找到对应的方法,进而就能完成执行的操作

谈了这么多问题,其实就是想引出关于中断的概念,而键盘的行为和操作系统的行为其实和信号十分类似,它们都遵循异步的逻辑,键盘怎么摁,操作系统不会专门去等着它,而是在摁完之后操作系统会在合适的时候对这个行为做出响应,那信号是不是也是类似呢?一个信号传递给进程,进程可能并不会立即做出响应,它会在完成了当前最重要的任务后,再对这个信号做出反应,这其实就是一个异步的逻辑原理,那信号中的这些各种各样的信号,是不是就如同对应的中断号,而中断向量表,不就是和kill列表中的各种信号是一样的吗?

因此得出的结论是,信号本身就是用软件来模拟中断的行为,只不过这两个操作在设计上是两套机制,一个是纯硬件,一个是软件上的操作,但是在响应和异步的方面,它们之间是有很多的相似处的

信号的产生

Ctrl+c的命令可以让前台的进程终止,那为什么呢?借助信号来解决这个问题

键盘中的数据是有很多种的,其中一种是1234这样的普通数据,一种是例如Ctrl+c这样的组合键,这样的数据被叫做是控制数据,它传递的是一种控制的思想观念,操作系统如果收到了普通数据,就把数据传递给用户进程,如果是组合键,就把这个数据转换成一种动作

因此从头理思路,在键盘上按下了Ctrl+c后,此时光电信号会由键盘控制器解析成中断信号,中断信号再传递到8259板进行解析,8259板再传递到对应的CPU上的针脚,CPU的针脚再进行解析,最终读取到数据,就会向进程发送2号信号,最终使得进程结束

所以,引出的结论是,Ctrl+c命令本质上就是一种组合键,它要传递的控制数据就是向进程发送2号信号,也就是说kill -2和Ctrl+c是等价的,具体可以通过看返回上一个命令的状态来看

signal系统调用

这里介绍一个系统调用:

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

该函数最终形成的效果是,如果有一个信号被发送,那么此时就会被替换为自定义的函数行为,因此这个函数的第二个参数实际上是一个函数指针

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

void handler(int singno)
{
    cout << "这是" << singno << "号信号" << endl;
    exit(1);
}

int main()
{
    signal(2, handler);
    signal(3, handler);

    while(true)
    {
        cout << "我的进程pid是" << getpid() << endl;
        sleep(1);
    }
    return 0;
}

在这里插入图片描述
从这个程序运行结果可以看出,Ctrl+C确实是传递的2号信号

在系统中信号主要分为有普通信号,下标从1到31,也有实时信号,那么这里只进行普通信号的研究

对于普通信号来说,它是没有0号信号的,为什么呢?

在进程等待的学习中就有这样的概念,一个进程的退出有两种信息,一个是退出时收到的信号编号,一个是退出时收到的退出码,所以对于进程退出来说是有两个数字可以参考的,退出信号和退出码,也是根据这两个数字来判断进程的健康状态的,加入进程的退出信号是零,表示的是这个进程在运行期间没有收到任何信号,它是很正常的跑完的,至于结果是否正确,则是可以根据进程的退出码来表示它到底退出的是否正确,由此可以看出,退出信号不应该有0号新号,如果有0号信号,那还能表示没有收到任何信号吗?因此在设计的时候大概率就没有进行对应的设计,就是为了更好的识别进程的正常退出这样的情况

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言进阶篇】assert宏 使用详解

文章目录 一、assert简介 二、assert使用方法和规则 2.1 头文件 2.2 原型 2.3 功能 2.4 示例 2.5 assert的打开与关闭 三、注意事项 3.1 运行效率问题 3.2 assert只适用于调试版本 3.3 资源释放与清理 3.4 过度依赖 四、总结 个人主页&#xff1a; 倔强的石头的…

web前端开发--------阴影与转换

1.阴影分为文本阴影和盒子阴影 我们使用text-shadow属性为文本添加阴影效果&#xff0c;使用结构伪类为第一个子元素p添加阴影效果&#xff1b; 水平偏移量为负值时&#xff0c;表示阴影向左偏移&#xff1b; &#xfeff;垂直偏移量为负值时&#xff0c;表示阴影向上偏移。 …

【PaddleSpeech】语音合成-男声

环境安装 系统&#xff1a;Ubuntu > 16.04 源码下载 使用apt安装 build-essential sudo apt install build-essential 克隆 PaddleSpeech 仓库 # github下载 git clone https://github.com/PaddlePaddle/PaddleSpeech.git # 也可以从gitee下载 git clone https://gite…

龙芯--自主架构先驱者

&#x1f6d1; 这是ren_dong的第23篇原创 1、概述 自主可控最高的 MIPS 架构 CPU 龙芯是我国最早研制的高性能通用处理器系列&#xff0c;拥有 MIPS 指令的永久授权&#xff0c;并拓展出了自己的指令集loong ISA。龙芯采用自主 Loong ISA 指令系统&#xff0c;兼容 MIPS 指令&a…

C语言——标准输出函数(printf、putchar和puts)

目录 1. 标准输入输函数出头文件2. printf2.1 函数申明2.2 基本用法2.3 占位符2.4 输出格式2.4.1 限定宽度2.4.2 总是显示正负号2.4.3 限定小数位数2.4.4 输出部分字符串 3. putchar3.1 函数申明3.2 基本用法 4. puts4.1 函数申明4.2 基本用法 1. 标准输入输函数出头文件 #inc…

由反射引出的Java动态代理与静态代理

写在开头 在《深入剖析Java中的反射&#xff0c;由浅入深&#xff0c;层层剥离&#xff01;》这篇文章中我们讲反射时&#xff0c;曾提到过Java的动态代理中使用了反射技术&#xff0c;那么好&#xff0c;今天我们要就着反射的索引&#xff0c;来学习一下Java中的代理&#xf…

不下载任何插件和依赖,在线导出swagger的api接口文档(word)

一、前言 swagger是一个非常方便用来生成api的工具集&#xff0c;它提供了可视化的restful风格的web界面&#xff0c;方便查看生成的api。 但是&#xff0c;想要将swagger生成的api直接导出为doc文档&#xff0c; 似乎不太方便实现&#xff0c;解析swagger的json串&#xff0c;…

空间计算时代加速到来,需要的不只是苹果

近年来&#xff0c;科技行业一直在期待“寒武纪”时刻。伴随技术革命的深入推进&#xff0c;所有厂商都预感新的时代即将到来&#xff0c;并期待自己成为那个引爆点&#xff0c;轻轻一触&#xff0c;推开一扇新的未来之门。 今年开年&#xff0c;苹果就为科技圈锚定了一个可能…

C#拆分字符串,正则表达式Regex.Split 方法 vs String.Split 方法

目录 一、使用的方法 1.使用Split(String, String)方法 2.String.Split 方法 二、源代码 1.源码 2.生成效果 使用正则表达式可以拆分指定的字符串。同样地&#xff0c;使用字符串对象的Split方法也可以实现此功能。使用字符串对象的Split方法可以根据用户选择的拆分条件&…

PythonWeb框架库之fastapi使用详解

概要 Python是一门广受欢迎的编程语言&#xff0c;用于构建各种类型的Web应用程序。FastAPI是一个现代、高性能的Web框架&#xff0c;它以简单的方式提供了快速构建API的能力。本文将介绍FastAPI的各种功能和用法&#xff0c;并提供丰富的示例代码&#xff0c;帮助大家开始使用…

帮管客CRM 文件上传漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

指针+一维整型数组的基本运用 和 指针+一维整型数组的初步学习

一&#xff0c;调式程序的技巧&#xff1a; 1.明确问题 2.定位问题 3.加打印&#xff08;打印核心数据0&#xff09; 二&#xff0c;指针的回顾 1.指针的概念&#xff1a;指针就是地址&#xff08;内存单元的编号&#xff09;&#xff0c;是一个数据类型&#xff08;指针类型…

使用 Dockerfile 定制镜像详解

使用 Dockerfile 定制镜像详解 1.DockerfileFROM 指定基础镜像RUN 执行命令构建镜像 2.COPY 复制文件3.ADD 更高级的复制文件4.CMD 容器启动命令5.ENTRYPOINT 入口点6.ENV 设置环境变量7.ARG 构建参数8.VOLUME 定义匿名卷9.EXPOSE 暴露端口10.WORKDIR 指定工作目录11.USER 指定…

【Django】如何设置支持多语种网站,中文/英文网站

首先&#xff0c;需要明确一点&#xff1a;我们要实现的中英对照翻译&#xff0c;这个翻译不是浏览器翻译的&#xff0c;也不是Django帮你翻译。这个需要你自己事先手动翻译好&#xff0c;存放在专门翻译文件中&#xff0c;Django只是事后调用而已。 第一步 新建项目后&#x…

Python||五城P.M.2.5数据分析与可视化_使用华夫图分析各个城市的情况(中)

目录 1.上海市的空气质量 2.成都市的空气质量 【沈阳市空气质量情况详见下期】 五城P.M.2.5数据分析与可视化——北京市、上海市、广州市、沈阳市、成都市&#xff0c;使用华夫图和柱状图分析各个城市的情况 1.上海市的空气质量 import numpy as np import pandas as pd impor…

【毕业日记】2024.01 - 慢下来,静待花开

转眼距离930离开鹅厂已经120天了&#xff0c;我是很能拖延的&#xff0c;或者是很懂自我麻痹的&#xff0c;这三个多月&#xff0c;一直想要写点东西纪念&#xff0c;一直拖一直拖一直拖…… 疫情这几年经济下行里裁员是个茶余饭后“嬉笑”之余经常被提起的词&#xff0c;部门滚…

JVM 笔记

JVM HotSpot Java二进制字节码的运行环境 好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;具有垃圾回收功能数组下标越界检查多态&#xff08;虚方法表&#xff09; JVM组成 类加载子系统&#xff08;Java代码转换为字节码&#xff09;运行时数据…

【代码随想录-链表】环形链表

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

GEDepth:Ground Embedding for Monocular Depth Estimation

参考代码&#xff1a;gedepth 出发点与动机 相机的外参告诉了相机在世界坐标系下的位置信息&#xff0c;那么可以用这个外参构建一个地面基础深度作为先验&#xff0c;后续只需要在这个地面基础深度先验基础上添加offset就可以得到结果深度&#xff0c;这样可以极大简化深度估…

【前端web入门第三天】02 CSS字体和文本

文章目录: 1.字体 1.1 字体大小 1.2 字体粗细 1.3 字体样式 1.4 行高 1.5 字体族 1.6 font 复合属性 2. 文本 2.1 文本缩进2.2 文本对齐方式2.3 文本修饰线2.4 color文字颜色 1.字体 1.1 字体大小 属性名: font-size属性值:文字尺寸&#xff0c;PC端网页最常用的单位px …
最新文章