【LINUX】进程间信号

news/2024/10/31 0:11:52/

文章目录

  • 前言
    • 铺垫
    • 信号
  • 信号的产生
    • 1、终端按钮产生信号
    • 2、调用系统函数向进程发送信号
    • 3、软件条件产生信号
    • 4、硬件异常产生信号
  • 信号的保存
  • 补充:位图数据结构
  • 信号的处理
  • 结语

前言

铺垫

1、日常中我们能经常感受到信号的存在:红灯停绿灯行、三更鸡鸣、妈妈的一通电话,这些都是信号,当我们遇到这些信号的时候,我们都知道接下来要做什么,进程也知道接下来要做什么,因为程序员在设计进程的时候就告诉他了。
2、信号可能随时产生,有可能进程在做优先级更高的事情,因此从进程产生到进程执行有一个时间窗口,同时进程也要有能够记录下这个信号的能力
3、信号的产生对于进程来说是异步的。
4、进程由操作系统通过pcb来管理,在对应进程的pcb里的某个位图结构记录着信号是否发生。
5、正因为是由操作系统维护,因此无论是通过哪种方法,都必须通过OS来写入!

信号

可以使用kill -l命令查看系统定义的信号列表,34号以后是实时信号,暂不讨论。
在这里插入图片描述

信号的产生

1、终端按钮产生信号

键盘在按下后会通过硬件单元告知cpu的特定针脚引发硬件中断,某个寄存器会存入9号信息,再通过中断向量表和中断号找到对应的方法,通过驱动程序来读取键盘的数据,再把数据给OS,OS会将其转化成2号信号再写入对应的位图结构,如下图:
在这里插入图片描述

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

alarm

#include <unistd.h>
功能:计时器int alarm(int seconds);
参数:seconds:秒数
返回值:返回0,如果进程被提前叫醒,就返回上次闹钟剩余的秒数

3、软件条件产生信号

先来学习一个函数:signal,我们知道进程拿到信号后会执行相应的动作,默认一般是退出,可以通过这个函数修改其执行动作。

#include <signal.h>
typedef void(* sighander_t)(int);
sighander_t signal(int signum,sighander_t handler);作用:设置某一个信号的默认动作
参数;signum:要处理的信号类型handler:函数指针,要设置的对应动作
返回值:返回信号处理函数指针
#include <signal.h>
#include <sys/types.h>int kill(pid_t pid, int sig)
作用:控制进程信号
参数:pid:哪个进程sig:发送几号信号
返回值:

4、硬件异常产生信号

除0的本质,就是触发硬件异常。
在这里插入图片描述

信号的保存

通过上面的四种方式,信号被OS写入到pcb对应的位图结构内,接下来我们再来看一下信号保存的相关细节:
在这里插入图片描述
在学习进程控制程序退出和异常的时候我们知道status的低七位是异常信号,低第八位称为core dump位,当时没有解释这一位代表什么,现在说明一下:
程序因信号退出会有两种方式:
1、Term:直接退出
2、Core:会先进行核心转储,再退出

OS可以在该进程异常的时候,核心代码部分进行核心转储,将内存中进程相关数据,全都dump到磁盘中。黑核心转储文件方便在异常后进行调试,可以用ulimit -a来查看是否开启。
在这里插入图片描述

像我这台服务器就没有打开,可以使用ulimit -c [size] 来指定核心转储文件的大小,一般云服务器都默认不开启,因为云服务器一般作为生产环境。


言归正传,信号是如何保存在对应的数据结构里的呢?
在这里插入图片描述
pending表:位图结构,比特位位置表示哪一个信号,内容表示是否收到该信号
block表: 位图结构,比特位位置表示哪一个信号,内容表示是否阻塞该信号
handler表: 函数指针数组,下标表示信号编号,内容表示该信号传递的动作

补充:位图数据结构

//TODO…

信号的处理

首先我们要先明确一个问题:信号可以被立即处理吗?
信号不是被立即处理的,而是在合适的时候,信号的产生是异步的,当前进程可能正在做更重要的事情,那什么时候合适呢?当进程从内核态切换回用户态的时候,进程会在OS的指导下,进行信号的检测与处理。

这里提到了一个概念:什么是内核态和用户态?

用户态:执行用户写的代码时,进程所处的状态
内核态:执行OS的代码时,进程所处的状态

为什么要有这样的区分呢?又是如何做到这样的区分呢?
在上次讲解进程地址空间的时候,我们知道进程地址空间通过一张 页表 来建立虚拟地址空间和物理内存之间的联系,其实这个页表分为两种:上次介绍的页表是用户级页表,还有一张内核级页表,一个进程的虚拟地址空间由两部分构成,其中0-3G为用户虚拟地址,3-4G是内核的虚拟地址,正式通过这张内核级页表,可以让进程完成系统调用。

总结:
所有的进程都有自己的用户级页表;但所有的进程都可以看到同一张内核级页表,这样就支持所有进程通过统一窗口,看到同一个OS,所以OS的本质都是在进程的地址空间内运行的,因此,系统调用的本质其实就是在自己的地址空间跳转并返回。

在这里插入图片描述
那么问题来了,进程如何完成上述跳转呢?进程又是如何被调度的呢?

一、如何完成上述跳转?
实际上在CPU内部有一个叫做CR3的寄存器
3、0分别表征当前运行的进程是用户态、内核态,当然用户是不可以直接更改系统级别的,在系统调用的时候,内部光遇在正式调用逻辑的时候,修改执行级别。
详细流程:

当一个进程的时间片到了或者要进行系统调用的时候,这个进程的状态就会由用户态切换成内核态,在内核态的进程就会开始检查是否有信号需要处理,当检查到有信号需要处理,进程就会再由内核态切换成用户态,完成用户自定义的方法,完成这个方法后,进程应当重新嵌入内核,再调用sys_sigreturn回到用户态执行后续代码。
在这里插入图片描述

二、进程是如何被调度的?
不知道大家有没有想过一个问题,每次电脑关机后,断电一段时间,即使不联网也可以获得当前的时间,原因在于位于PC主板CMOS内的时钟硬件!

回到这个问题,首先我们要清楚:进程是由操作系统管理的,操作系统是一个软件,本质是一个死循环,而OS时钟硬件,每隔一段很短的时间就会向OS发送时钟中断,OS就要执行对应的中断方法,然后检查当前进程的时间片,通过系统调用函数:schedule() ;如果发现进程的时间片到了,就将进程对应的上下文进行保存并切换,再选择合适的进程。

结语

以上就是进程间信号的全部内容了,感谢收看,这里是蓝色学者,我们下次再见。


http://www.ppmy.cn/news/107863.html

相关文章

双二阶环路滤波器时频域分析

【设计目标】对双二阶环路滤波器进行时频域分析和处理的基本方法 【设计工具】MATLAB【设计要求】 1)分析典型的双二阶环路滤波器电路:低通、高通、带通、带阻 2)理论分析各滤波电路的系统函数 3)利用Matlab分析各滤波电路的系统函数的频率特性(幅频、相频)、零极点分布…

不到一分钟,即刻拥有这 22 款插件主题

开源 API 管理工具 Postcat 的插件广场最近上新了插件主题&#xff0c;看了看&#xff0c;真的有几款我很喜欢。可能会有朋友有跟我一样的疑问&#xff0c;如何拥有这些好玩的插件主题。 第一步当然是找到 Postcat &#xff0c;安装 Postcat ! 找到插件广场 浏览并选择喜欢的主…

视觉与激光雷达融合3D检测(一)AVOD

1.概述 AVOD&#xff08;Aggregate View Object Detection&#xff09;和MV3D类似,是一种融合3维点云和相机RGB图像的三维目标检测算法. 不同的是: MV3D中融合了相机RGB图像,点云BEV映射和FrontView映射,而AVOD则只融合相机RGB图像和点云BEV映射. 从网络结果来看,AVOD采用了基…

zabbix监控山石防火墙

一、导入监控模板 <Template Net Hillstone StoneOS SNMPv2> 导入前请确保zabbix内置的模板Template Net Network Generic Device SNMPv2存在。 支持山石E系列和X系列防火墙 兼容Zabbix 4.x和5.x。 二、监控内容 SNMP状态和接口速率由Template Net Network Generic De…

Spring5 学习笔记

前置知识&#xff1a; 掌握Java基础知识&#xff08;特别是反射&#xff09;掌握Java注解掌握XML掌握Maven Spring5学习笔记 1、Spring概述1.1、简介1.2、优点1.3、组成1.4、拓展 2、IOC理论推导2.1、分析实现2.2、IOC本质 3、HelloSpring3.1、导入jar包3.2、编写代码3.3、思考…

《ChatGPT Prompt Engineering for Developers》课程-提示词原则

编写 Prompt 的原则 本章的主要内容为编写 Prompt 的原则&#xff0c;在本章中&#xff0c;我们将给出两个编写 Prompt 的原则与一些相关的策略&#xff0c;你将练习基于这两个原则来编写有效的 Prompt&#xff0c;从而便捷而有效地使用 LLM。 一、环境配置 本教程使用 Open…

条件变量基本使用

一、条件变量 应用场景&#xff1a;生产者消费者问题&#xff0c;是线程同步的一种手段。 必要性&#xff1a;为了实现等待某个资源&#xff0c;让线程休眠。提高运行效率 int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); int pthr…

附录5-黑马头条案例

目录 1 效果 2 组件库vant 2.1 安装 2.2 配置 2.3 项目中的使用 2.3.1 引用 2.3.2 tabbar 底部切换 2.3.3 navbar 顶部标题 2.3.4 van-list 上拉触底更新 2.3.5 van-pull-refresh 下拉更新 2.3.6 v-cell 2.3.7 van-icon 2.3.8 自定义风格 3 保持滚…