Linux信号(一).信号产生

一.何谓信号?

信号的到来会让进程中断正在做的事情,告诉进程该做另一件事了;这是一种给进程发送的,用来进行事件的异步通知机制!

那什么又是异步通知呢?

异步:两件事情在同时发生,互不干扰 。所以**信号的产生相对于进程的运行,是异步的。**产生信号和进程运行,是各干各的事情,互不干扰。就像蒋校长在水饺是一件事,同时闹钟响了,这个信号产生又是一件事,这俩事在闹钟响的一刹那,是异步的。

小结论:

1.信号处理 :在红灯没有亮时,我就知道红灯亮,该停下。同样,对于进程来说,在信号没有产生的时候,它就知道信号该怎么处理了。

**2. 信号的处理,不是立刻就处理,可以等一会再处理,在合适的时候处理就行了。**就像闹钟响了,我还是很困,那可不可以眯会再处理闹钟呢?那当然可以。

3.人能知道信号出现以后,怎么处理(识别信号),是提前被人或事"教育"(拷打)过的;进程亦是如此,教进程识别信号的,是设计进程的OS程序员,进程早就被程序员内置了对于信号的识别与处理方式!

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

二.信号的产生

1.键盘产生信号

就比如一直在用的,键盘上输入ctrl+c就可以结束掉一个进程,ctrl+c就是给目标进程发送信号。相当一部分进程,对信号的处理动作,就是让自己终止。

①.键盘产生的信号都有哪些?------ctrl+c给进程发的是哪一个信号呢?

用kill -l指令,就可以看到所有的信号:

这些信号都是一个个整型数字,为了可读性更好,会把这些数字定义成宏,这些宏就展示了对应信号的处理动作。

34-64是实时信号,我们不考虑它们。我们着重学习的是1-31号的普通信号,这些信号就像上面说的,可以等一会再处理,不需要马上处理。

那么回到标题的问题,ctrl+c发送的是哪一个信号呢?答案是2号信号。

②.如何证明发的是2号信号呢?

进程在收到信号后都会有三种处理动作:

1.默认处理动作,就像遇到红灯亮时,好市民会有素质的停下等红灯。

2.自定义信号处理动作(自定义捕捉),就像从疯人院里逃出来的人,遇到红灯亮时,会跳舞。

3.忽略处理。就像低素质人群遇到红灯亮时,赌自己不会撞大运,一脚油门冲过去。

而相当有部分的进程,在收到信号以后,默认的处理动作,就是让自己终止。

注意:为了防止所有信号因恶意的自定义捕捉,导致进程再也结束不了,9号信号永远无法被自定义捕捉!

要证明发的是2号信号,就要看到信号的处理过程,想要看到信号的处理过程,可以更改进程的默认信号处理动作,可以调用一个系统调用函数:

返回值是个typedef的函数指针。第一个形参signum是上面的信号(数字或者宏),第二个形参也是个函数指针,当使用该函数后,某个信号发给当前进程时,当前进程不再执行对应信号的默认动作,反而执行函数指针指向的方法(函数)。 也就是说这个函数可以玩信号处理动作的自定义。

我们来使用一下这个函数,对2号信号的处理动作做修改:

这时ctrl+c一下,发出信号以后,进程做出的处理动作,就变成打印上面那句话了:

既然我改了2号信号的处理动作,然后ctrl + c信号发给进程后,进程做的处理动作是我更改过的2号信号的处理动作,这就必然能说明ctrl + c发给进程的是2号信号。

③.目标进程是??前台or后台进程

Ⅰ.概念理解------前台与后台进程

在命令行直接运行某进程:#./xxxx ------该进程被叫做前台进程 。键盘产生的信号,只能发给前台进程。

如果是:#./xxxx & ------这里产生的,就是后台进程 。后台进程 对通过键盘的ctrl+c发出的信号,不做处理。而且ctrl+c是输入给前台bash进程的,bash进程本身是不会被ctrl+c结束掉的,它在用户退出登录时,才会终止。

那么如何终止后台进程呢?

用指令给目标进程发信号,直接输入kill -9 + 目标进程pid指令。9号信号很强势,可以让后台进程结束。

Ⅱ.前台进程vs后台进程

只有前台进程能从键盘获取标准输入,原因在于键盘只有一个 ,输入数据一定是给一个确定 的进程。而前台进程有且只有一个,符合确定这一条件。

在没有启动任何程序时,我们系统里一直有个进程为我们提供服务,该进程就是命令行shell进程!该进程开始时是个前台进程。所以我们能够在命令行用键盘输入指令。

当然,前后台进程不是一成不变 的,当./xxx启动程序,产生进程时,目标进程会成为前台进程,而bash进程转而成为后台进程,虽然目标进程是前台,但如果进程内没有调用scanf等,从键盘获取数据的接口,那么前台目标进程依旧对键盘发送的信号无感。

当./xxx &启动程序,产生进程时,进程是后台进程,bash进程还是前台进程。

Ⅲ.前后台移动的指令

ctrl+z:将进程从前台提到后台 ,它本质是将进程暂停,前台进程是不能被暂停的,它要一直等待用户输入,一旦被暂停了,就会卡死,键盘输啥都没用了,所以某个前台进程一旦被ctrl + z了,就会被提到后台,然后暂停。

bg + 任务号(jobs有显示):**让暂停的后台进程重新运行起来。**bg就是back ground的意思。

回到疑问,ctrl + c是给目标进程发信号的,既然支持从键盘获取标准输入,那么目标进程是一个前台进程。

④.什么叫给进程发信号?

信号产生以后,并不是立马处理,所以要求进程把信号记录下来,到合适的时候处理。那么就会引出两个问题:记录在哪里 和如何记录。

记录在目标进程的PCB------task_struct里,在task_struct里有个unsigned int的位图------sigs,它拥有32位,比特位的位置,代表信号编号;比特位的内容,代表是否收到,1就是收到。

所以我们回到问题,给进程发信号的本质其实是向进程写信号,本质的本质,是修改位图! 从上面两个问题的答案,我们可以知晓,想要修改位图,需要准确定位对应的信号,就需要进程的pid和信号编号。修改位图,只需要根据这两个数据,找到对应信号,把0置为1就行了。

但是task_struct属于OS内部的数据结构对象,是内核级 的,修改位图,就是修改内核数据 ,这事只能让OS来做!所以无论以什么方法产生,发送信号,在底层必须让给OS来发送!因而,用户想要让OS发信号,就必须提供相应的系统调用。

2.系统调用产生信号

①.kill

cpp 复制代码
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

作用:向进程/进程组发送信号

注意:名字叫kill,但不一定是杀死进程,只是发送信号。信号是什么,目标进程就做对应的动作。

第一个参数 pid(高频考点,必背)

1. pid > 0 :信号发给 PID等于pid的这一个进程

  1. pid = 0 :信号发给当前进程所在进程组的所有进程

  2. pid < -1 :信号发给进程组ID = -pid 的整个进程组

  3. pid = -1 :发给当前进程有权限发送信号的几乎所有进程(除init进程)

特殊: sig = 0 ,不会发送任何信号,只做权限和PID是否存在的检测,用来判断进程是否存活。

第二个参数 sig

要发送的信号编号/宏 :

  • SIGINT 2号信号(Ctrl+C)

- SIGKILL 9号,强制杀死,不能被捕获、不能忽略

  • SIGTERM 15号,默认kill命令发的信号,可以被捕获处理

②.raise

自己给自己发信号,形参是信号编号(宏)。

③.abort

给当前进程(自己给自己)固定发6号信号,引起进程的终止。哪怕6号信号做过信号捕捉,在abort这儿发出去的,也是原版退出进程的6号信号。

3.使用指令kill来发送信号

没什么说的:

kill + 信号编号 + PID

4.通过硬件异常产生信号

进程除0的错误操作以后,为什么进程会崩溃呢?答案是进程收到了**8号信号,**结束了!

8号信号显示的是浮点数异常:

进程进行野指针的操作后,收到11号信号,也结束了。

11号信号显示的是段错误:

野指针的虚拟地址为0(nullptr),0号地址在页表中并不存在映射关系 ,因此没法映射到物理内存中。而比对页表做映射的是cpu里的硬件单元------MMU。野指针(0号地址)想要做映射转化物理地址时,CPU内CR3寄存器会把其内部页表的起始地址交给MMU,然后把0号地址这个虚拟地址也同时交给MMU,由于不存在映射关系,MMU转化失败,然后硬件报错; 作为软硬件的管理者,OS在收到报错以后,就会向进程发送11号信号,进程随即结束。

相关推荐
FfHUCisI1 小时前
sync.Once 与 sync.Cond 源码与并发控制陷阱
服务器·开发语言·后端·golang
爱签AI电子合同2 小时前
电子合同上手成本怎么测?易用性维度专项测评
服务器·人工智能·智能合约·企业微信
aixingkong9215 小时前
Nvidia为例 XPU的Multi-Host、Socket Direct 、GPUDirect、RDMA 技术点分析
服务器·网络·硬件架构·硬件工程
雯宝7 小时前
mnt_init 函数
linux
律宏阔13 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔13 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴13 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千13 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei3713 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化