【探索进程信号】:信号捕捉

个人主页: Rhzkp-CSDN博客

Linux专栏:戎小半的Linux_Rhzkp的博客-CSDN博客

目录

异步与同步:

信号的产生

前台进程与后台进程

什么叫做给进程发信号

信号vs通信IPC

信号产生方式

用户产生信号

系统产生信号

软件产生信号

信号处理

默认处理方式

自定义信号处理函数

捕捉信号

捕捉信号的过程

重谈捕捉

用户态与内核态

硬件中断

软件中断


信号:闹钟,红绿灯,上课铃声...

什么叫做信号:中断我们人正在做的事情,是一种事情的异步通知机制

换做进程就是:信号是一种给进程发送的,用来进行事件异步通知单独机制

异步与同步:

我在上课,快递到了,让张三去拿,在张三回来之前,先自习,回来之后再继续讲--- 同步

我在上课,快递到了,让张三去拿,课程不因为张三而停止,继续上课----异步

也就是说,进程1的运行不会影响到进程2,这就是异步,会影响到就是同步

基本结论:

  1. 信号处理,进程在信号没有产生的时候,早就知道信号该如何处理了。

  2. 信号的处理,不是立即处理,而是可以等到合适的时候,再进行信号的处理

  3. 人能识别信号,是提前被教育过,OS程序员设计的进程,在进程内部内置了对于信号的识别和处理方式

  4. 信号源非常多---给进程产生信号的信号源,也非常多

信号的产生

  • 键盘产生

如:ctrl+c是给目标进程发送信号的。相当一部分信号的处理动作,就是让自己终止。

1-31是普通信号,即可以不被立即处理的信号

32-64是实时信号,需要被立即处理的信号

  • 普通信号的处理:
  1. 默认处理动作---红灯亮的时候,停下来等

  2. 自定义信号处理---红灯亮的时候,跳舞

  3. 忽略处理---红灯亮的时候,继续走,不管红灯

前台进程与后台进程

./XXX ---前台进程

./XXX &---后台进程

  • 前台进程:可以从标准输入中获取数据
  • 后台进程:不可以从标准输入中获取数据。

这两者都可以向标准输出打印数据。

为什么后台进程不能从标准输入获取数据?

  • 键盘只有一个,输入数据一定是给一个确定的进程的,这个确定的进程就是前台进程,前台进程的本质就是从键盘获取数据

前台进程只能有一个,后台进程可以有多个

查看所有的后台任务

  • jobs

查看所有前台的任务

  • fg + 进程号(任务号)

将前台进程放到后台

  • ctrl + z

前台进程只能有一个,它是用来接收用户输入的数据的,所以前台进程不能暂停,一但暂停了,OS就会把他移到后台

让被被暂停的后台进程恢复运行

  • bg+任务号

什么叫做给进程发信号

信号发送给进程后,会被保存在task_struct对象中的sigs中,以位图的结构进行保存。比特位的位置,就是信号的编号,比特位的内容,表示是否接收到信号

  • 发送信号的本质:向目标进程写信号,修改位图!只要直到进程的pid与信号编号就行。

但是我们知道,信号是写到taskstruct中的,而taskstruct是内核中的数据结构对象,所以修改位图的本质:修改内核的数据。而内核数据用户自己是无法修改的,所以最终还是由OS来修改,所以,OS必须提供发送信号的系统调用。

kill就是封装了系统调用的c语言程序

不管信号是怎么产生的,发送信号在底层,必须让OS发送

信号vs通信IPC

  • 信号是人通过操作系统与进程交流
  • 通信IPC是进程与进程之间进行通信

信号产生方式

用户产生信号

用户通常可以在终端中按下特定的组合键来产生信号

如:

ctrl+c:产生 SIGINT 信号,用于中断当前正在运行的进程

ctrl+ \:产生 SIGQUIT 信号,不仅会终止进程,还会生成核心转储文件

使用 kill 命令:用户可以使用 kill 命令向指定进程发送信号

系统产生信号

  1. 进程异常:当进程发生异常时,如段错误(访问非法内存地址)、除零错误等,系统会向该进程发送相应的信号
  2. 段错误:即野指针的访问
  3. :当进程执行除法运算时,如果除数为零,会产生除零错误,系统会向该进程发送 SIGFPE 信号。(浮点信号)
  4. 系统资源相关:当系统资源达到一定阈值时,也可能产生信号。例如,当进程使用的内存超过了系统限制时,系统可能会发送 SIGKILL 信号来终止该进程,以防止系统内存耗尽。不过,这种情况通常需要系统进行相关的配置和监控。

软件产生信号

使用 kill 函数:在C 语言编程中,可以使用 kill 函数向指定进程发送信号。

使用 raise 函数:进程可以使用 raise 函数向自身发送信号。

信号处理

默认处理方式

每个信号都有一个默认的处理方式,常见的默认处理方式包括:

  1. 终止进程:如 SIGINT、SIGTERM 等信号的默认处理方式是终止进程。

  2. 生成核心转储文件并终止进程:例如 SIGQUIT 信号,在终止进程的同时会生成核心转储文件,该文件包含了进程在收到信号时的内存状态等信息,可用于调试程序。

  3. 忽略信号:有些信号(如 SIGCHLD,子进程状态改变时发送给父进程的信号)的默认处理方式是忽略。

自定义信号处理函数

进程可以通过调用 signal 函数或 sigaction 函数来设置自定义的信号处理函数

其中,signum 是信号编号,handler 是指向信号处理函数的指针。

捕捉信号

产生信号后,如果不需要立即处理则会将信号保存,等到合适的时候在处理
这个合适的时候是什么时候?

捕捉信号的过程

  • 如果信号的处理是用户的自定义函数,则在信号递达时就调用这个函数,这称为捕捉信号

在进程执行时,有时候会因为某些原因,进入到操作系统内部,如"系统调用",进入OS内部后,处理完则会回到当时的代码处继续执行。当内核处理完后,回到代码处之前,OS会检查当前进程是否接收到信号与该信号是否被block,如果收到信号且没被block,OS就直接进行信号处理

  • 在进程从内核态回到用户态时,会进行信号检查
  1. 内核态指的就是OS的身份。平时调用系统调用,在用户层调用系统调用,然后由OS执行系统调用
  2. 用户态,平时写的代码,如for循环、while循环、各种方法,这些就是在用户态执行的

检查信号的接口是dosignal()。dosignal检查的就是block、pengding、handler这三张表。如果收到信号同时没被block并且是自定义处理的,则会跳转到用户态的用户自定义处理函数处,执行函数。执行完后再返回到内核,再由内核返回到当时的代码处。

在检查信号时,发现信号是忽略的(SIG_IGN),则直接将Pengding表中对应的信号位写0,然后返回到代码处就行。

如果是默认的(SIG_DEF),则直接执行默认处理方式就行。

重谈捕捉

当执行信号的自定义处理函数时,OS也要做身份的切换,从OS转换为用户为什么?

  • 防止用户在自定义函数中,做非法操作,比如修改系统的配置文件

在执行完自定义处理函数时,是怎么回到内核的?

进程凭什么进入内核?

因为进程在执行时,会被cpu调度。而每个进程都是有自己的时间片的,当时间过后,就会被OS强制剥离下来。也就是说,是被OS强制进入的内核态的

用户态与内核态

硬件中断

操作系统是怎么运行的

  1. 操作系统怎么知道键盘上有数据了
  • 外部设备会与CPU特定的针脚进行间接的连接。比如键盘,当键盘被按下回车,就会向CPU发送硬件中断的东西

简单来说就是:外设发送高电频告诉中断控制器自己准备好了,中断控制器再生成对应的中断号,当cpu读取到这个中断号后,就去中断向量表里查找对应的方法并执行中断方法,读取数据,将数据搬到内存。也就是冯诺依曼体系

  • 这个中断向量表IDT就是OS的一部分

OS再也不关注外设是否准备好,而是外设准备好后会通知cpu

硬件发中断与发信号类似:

发中断---发信号

保存中断---保存信号

中断号---信号编号

处理中断---处理信号、自定义捕捉

信号是纯软件的,它本质是在模拟硬件中断。信号与中断在思想上是打通的

当中断没来的时候,cpu在做什么

  • 什么都没做,只是在不断暂停

在中断向量表中,有一个进程调度的中断服务

当时钟源发送中断给cpu对进程进行调度时,会检查进程的时间片是否结束,结束了就进行调度,没结束就直接返回

有没有可能因为软件的问题,也触发硬件中断的逻辑?

当进程执行自己的代码,执行到a/=0时,就会造成除0错误,导致硬件溢出。这种错误可以规定成为一种由cpu内部触发的中断。同时也会生成一个中断号。

但实际上这是由软件导致硬件中断

软件中断

  • 上述外部硬件中断,需要硬件设备触发。

  • 有没有可能,因为软件原因,也触发上面的逻辑?有!

  • 为了让操作系统支持进行系统调用,CPU也设计了对应的汇编指令(int 或者 syscal),可以让CPU内部触发中断逻辑

软件中断(Software Interrupt)是一种由程序或操作系统主动触发的中断机制,用于实现进程间的通信、系统调用、异常处理等功能。与硬件中断不同,硬件中断是由外部设备(如输入设备、网络接口卡等)触发的,而软件中断则是程序内部通过特定的指令或操作触发的中断

当我们进行系统调用的时候,具体是怎么进入OS完成系统调用的。

在OS内部,有一张系统调用表,实际上就是一个函数指针数组,里面记录了系统调用。因为是数组,所以这些系统调都会有自己对应的下标,这些下标叫做"系统调用号"

在调用系统调用的时候,其实就是 syscalltable[n]。

当用户调用系统调用的时候,就是将系统号move到寄存器中,在调用INT 0x80来触发软件中断比如

复制代码
int open()
{
  move n eax
  INT 0x80
}

OS接收到这个系统号,就回去系统调用表里查找对应的系统调用,然后执行系统调用。

所以OS不提供任何系统调用接口,只提供系统调用号。这些系统调用都是被glibc封装的

这些系统调用是用汇编实现的

  • 操作系统就是躺在中断处理例程上的代码块!

  • CPU内部的软中断,⽐如int0x80(32位下)或者syscall(64位下),我们叫做陷阱

  • CPU内部的软中断,⽐如除零/野指针等,我们叫做异常。(所以,能理解"缺页异常" 为什么这么叫了吗?)

系统调用的过程,也是在进程地址空间上进行的。
所有的函数调用,都是在地址空间之间跳转

相关推荐
巴里巴气1 小时前
zookeeper基本概念介绍
linux·分布式·zookeeper
codu4u13142 小时前
Maven中的bom和父依赖
java·linux·maven
IT成长日记4 小时前
【自动化运维神器Ansible】Ansible常用模块之hostname模块详解
运维·自动化·ansible·hostname·常用模块
lixzest4 小时前
Linux 中,命令查看系统版本和内核信息
linux·运维·服务器
朱小弟cs64 小时前
Orange的运维学习日记--16.Linux时间管理
linux·运维·学习
chen_note5 小时前
LAMP及其环境的部署搭建
linux·运维·mysql·php·apache·lamp·phpmyadmin
夕泠爱吃糖5 小时前
Linux 操作系统
linux·运维·服务器
数据要素X5 小时前
【数据架构10】数字政府架构篇
大数据·运维·数据库·人工智能·架构
专注VB编程开发20年5 小时前
winsock socket通讯为什么UDP服务器无法获取客户端IP?
服务器·tcp/ip·udp
G_H_S_3_5 小时前
【网络运维】 Linux:使用 Cockpit 管理服务器
运维·服务器·网络