初步理解Linux进程信号的处理过程 + Linux常见信号

生活中能看到信号的场景有闹钟、红绿灯、信号枪 ... 等,每当我们看到信号,都会做出对应的反应。进程也是如此,进程具有识别并处理信号的能力。

下面我们需要对进程信号有一个初步的了解,信号是怎么发送的?又是怎么处理的?


目录

一、进程信号的初步理解

1、进程收到信号就会立即处理吗?

2、没有被立即处理的信号放在哪?

3、谁负责把信号存到指定位置?

4、信号从产生到被处理所经历的过程

(1) 信号发送

(2) 信号保存

(3) 信号捕捉和处理

三、信号处理函数signal

四、Linux中已有的信号

1、信号总览

2、2号信号 SIGINT

3、3号信号 SIGQUIT        

4、9号信号 SIGKILL(无法被捕捉的信号)

5、8号信号 SIGFPE

6、11号信号 SIGSEGV


一、进程信号的初步理解

1、进程收到信号就会立即处理吗?

进程收到某种信号的时候,并不是立即处理的。比如远处看到红绿灯变成红灯,我们会立即停下吗?并不会,我们会把看到红灯这件事记录在大脑中,等走到路口再停下

进程当前可能在执行优先级更高的东西,所以要选择合适的时候再处理这个信号。

2、没有被立即处理的信号放在哪?

我们看到红灯的时候,会把看到红灯这件事存在大脑中。

既然信号不能被立即处理,已经到来的信号会被暂时保存起来,以供在合适的时候处理,应该保存在哪里呢??——》进程控制块 task_struct

3、谁负责把信号存到指定位置?

信号的本质就是数据,发送信号 ——》向进程控制块 task_struct写入数据 ——》但是进程控制块属于内核,内核不相信任何人,所以由谁来写入数据 ——》 OS!!

4、信号从产生到被处理所经历的过程

信号发送的过程可以通过下面这张图来表示,后面会针对每一步都会作详细的介绍,整个过程一共分成了三步:

(1) 信号发送

信号发送的方式多种多样,可以是键盘发送,如Ctr + C发送2号信号、Ctrl + \ 发送3号信号

也可以是通过命令行指令发送,如

kill -9 进程pid         #给对应的进程发送9号信号

 注意:第二种方式是通用的方法,2号信号也可以这样发送,如 kill -2  进程pid

(2) 信号保存

前面也提到了,信号是保存在进程控制块里面的,由OS来保存,具体的保存方式是 位图保存

我们常见的信号有31个,也就是前31个,我们可以理解为进程使用无符号32位的整型来保存我们收到的信号(实际上Linux中位图的保存没有这么简单,这个在“信号保存”的博客中也会说明

当没有收到信号时,所有的比特位都是0,类似于 0000 0000 ....

当我们收到了2号信号时,那就类似于 0100 0000 ....

struct task_struct
{
    uint32_t sigs;    //0000 0000 0000 ...
}

(3) 信号捕捉和处理

后面会提到一个阻塞的概念,被阻塞的信号无法被捕捉到,既然无法被捕捉,自然就无法被处理,你托中间人给 同事甲 送生日礼物,中间人把礼物丢了,同事甲自然就没法处理礼物了

三、信号处理函数signal

下面要结合代码介绍Linux中常见的信号,所以这里就简单了解一下信号的处理函数signal函数,后面信号捕捉还会再说明一次,signal函数就是建立起某个信号和对应处理函数的连接,等真正接收到这个信号的时候,就会执行对应的处理函数。

第一个参数,是信号的序号,上面已经列出了信号以及对应的序号,既可以用序号,也可以使用信号名

第二个参数,是接收到信号以后处理信号的函数指针

返回值:调用成功,则返回上一次信号处理函数被调用的返回值;调用失败,返回SIG_ERR

              因为存在无法找到对应的函数的情况,所以就无法搭建起信号和信号处理函数之间的联系

signal(2,signalhandler);    //建立起2号信号和signalhandler函数之间的关系
                            //等实际收到2号信号时,就会执行signalhandler函数

 

四、Linux中已有的信号

1、信号总览

我们在命令行输入 kill -l 就可以看到Linux中已经定义好的信号

需要注意的是,看似有64个信号,我们看看黄色下划线部分会发现缺少32、33号,实际上,我们真正要了解的只是前31个信号的一部分,34号以后的,暂不考虑 

下面就正式了解前31个信号中的一部分信号

2、2号信号 SIGINT

2号信号的作用是 中止进程,快捷键是Ctrl + C

下面我们用一个小测试来验证一下,下面的代码能接收 前31个信号

 一开始我们不发送信号,进程只是在打印内容

 当我们 Ctrl + C的时候,OS就会发送2号信号,此时对应的操作除了退出进程外,还会打印一句话,从结果来看,测试成功了,Ctrl + C发送的就是2号信号

3、3号信号 SIGQUIT        

3号信号的作用是 终止进程并Core Dump,快捷键是Ctrl + \

Core Dump是指进程异常中止的时候,把进程用户空间的内存数据保存到磁盘上,文件名为core

 我们沿用处理2号信号的代码,这里我们就直接展示结果

4、9号信号 SIGKILL(无法被捕捉的信号)

9号信号的作用是 杀死进程同时无法被捕捉到(无法被捕捉到就说明,我们无法修改该信号的默认处理方式)

由于没有快捷键,我们需要新建一个SSH渠道来发送9号信号给当前进程,下面依然沿用2号信号的代码,进程开始运行以后就像下面这样

 我们发送9号信号以后,结果进程没有打印回调函数的内容就退出了,因此 9号信号是无法被捕捉的!!

5、8号信号 SIGFPE

8号信号是浮点数异常,比如 1/0的情况

我们稍微修改一下2号信号的代码,故意加入 1/0 的情况,一开始不使用signal函数接收信号,看看进程的默认处理方式

 下面加入signal函数,结果发现,实际上我们收到的就是8号信号

6、11号信号 SIGSEGV

11号信号是在 进程崩溃的时候发送的

下面我们稍微修改一下 2号信号的代码,故意让程序崩溃,一开始我们不使用signal函数接收信号,看看程序崩溃时,会有什么反应

 很显然,进程崩溃了,下面我们使用signal函数试试,看看我们接收到的是不是11号信号

 因此我们可以得出一个结论,当进程崩溃退出的时候,实际上是接收到了第11号信号!

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值