Linux信号详解

目录

前言

一、信号概念

1、生活中的信号

2、计算机中的信号 

3、实现信号捕捉

二、产生信号的方式

1. 通过终端按键产生信号

格外拓展:核心转储(core dump)

status 

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

3. 由软件条件产生信号

 4、硬件异常产生信号

三、阻塞信号

1、概念

 2、内核中的表示

3、信号集操作函数

3.1用户层函数

3.2 系统接口

四、信号捕获

1、用户态和内核态 

2、内核如何捕获进程信号

2.1捕获信号过程

2.2 sigaction

五、函数的重入

六、c语言关键字volatile

总结


前言

哈喽,小伙伴们大家好,本篇文章我将和大家一起学习进程信号。进程在某种意义上其实和我们人很像。在大多数情况下,我们的日常生活就是起床、上课、学习、休闲、休息,按部就班的度过每一天。但有时候也会遇到突发状况,比如生病啦,或者家里突然有事需要回家啦,这些突发状况是不可避免的,因为往往是事情推着人走的,我们要有处理突发状况的能力。进程也是如此,通常情况下按部就班的运行着,但保不齐什么时候就遇到突发状况,为了保证进程能在突发状况中做出相应的处理,信号由此产生。操作系统会根据突发状况给进程传递不同的信号,让进程做出相应的处理。看到这里,大家是不是感觉到了信号是一个非常有用的东西呢,那么事不宜迟,拿好小本本,和我一起开始信号的学习吧。


一、信号概念

1、生活中的信号

信号不仅仅存在计算机中,同样存在我们的日常生活中。在谈计算机中的信号前,我们先来聊聊生活中的信号。

在日常生活中,信号与我们的关系有如下特征:

  • 信号还没有产生的时候,我们要知道如何识别信号,并且知道接收信号后该如何反应。比如我们过马路时,我们首先需要知道红绿灯是一种信号,并且知道根据颜色的不同做出什么反应。这些东西往往是小时候爸爸妈妈教给我们的。所以我们得出一个结论:我们能够识别的信号特征,以及相应的处理过程是因为之前有人对我们进行过"教育"。
  • 当信号产生的时候,我们不一定要立刻去处理信号,因为我们可能有优先级更高的事情。比如我们正在打游戏的时候显示快递到了,我们不会立刻去取,而是等游戏打完后找一个合适的时间去取。
  • 信号已经产生,但我们暂时没有处理,那么一定要有某种方式记录这个信号已经产生。比如我们收到快递到了的信号后没有立刻去拿,但手机里的短信记录着快递已经到了。
  • 处理信号时往往有三种方式:默认行为,自定义行为,忽略行为。比如我们在过马路的时候遇到红灯,默认行为是站在原地等。但有一次我突然想上厕所,于是趁着红灯的时间去了一下路边的厕所,这就是自定义行为。而忽略行为就是不管红灯的提示,径直走过马路。

2、计算机中的信号 

在计算机中,进程就好比生活中的人,信号有以下特征:

  • 进程虽然现在没有受到信号,但是进程一定知道如何识别信号和做出相应反应。程序员在设计进程的时候已经内置了处理方案,信号是进程中特有的特征。
  • 进程在收到信号时可能不会立即处理,因为有优先级更高的事情。如果这样需要先把信号记录下来,等合适的时候再处理。
  • 进程处理信号有三种方式:(1)默认行为:终止进程,暂停,继续运行等。(2)自定义行为,由我们自己编写。这种方式也称为捕捉一个信号(3)忽略信号。

可以看到,计算机中的信号和生活中的信号其实是很相似的。下面我们思考两个问题:

信号是如何记录的?

我们先来谈谈信号是如何记录的,在学习进程时候,我们应该了解了每个进程都对应一个task_struct(PCB),在这个task_struct中,记录着进程的各种信息,各种信息中同样也包括信号的记录。信号在task_struct中是以位图的方式记录的,task_struct有变量signal,可以把它的类型理解成无符号整数。比特位的位置为信号编号,比特位的内容为是否收到信号,假如收到6号信号就会把第六个比特位置1。我们可以通过下面的命令查看信号编号。

命令:kill   -l         功能:查看系统定义的信号列表       

  •  每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有定义 #define   SIGINT   2
  • 31号之前为普通信号,34号之后为实时信号,本章我们主要讨论普通信号。

 信号是如何发送的?

进程收到信号,本质上是进程的信号位图被改了。那么谁有权限改进程内的东西呢?答案当然是OS,操作系统是进程的管理者,拥有绝对的权限。所以信号发送的本质就是操作系统修改了进程的信号位图,进程根据修改后位图的值做出相应处理。

3、实现信号捕捉

signal函数

原型:signal(int sig, void (*func)(int))     

功能:用来自定义信号处理方式

参数:

  • sig:信号编号
  • func为函数指针,传入的函数为信号的处理方式

代码如下:

 代码运行结果如下,ctrl+c对应的是信号2,终止进程。我们可以发现信号2被我们自定义了。

注意:有些信号是不能被捕捉的,因为如果所有的信号都被捕捉,那么操作系统就再也没有办法杀死进程了。

二、产生信号的方式

1. 通过终端按键产生信号

通过终端按键也就是通过键盘产生信号,比如我们常用的ctrl+c。ctrl+/。

注意:

  • Ctrl-C 产生的信号只能发给前台进程。Shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接到像 Ctrl-C 这种控制键产生的信号。
  • 一个命令后面加个&可以放到后台运行,bash默认是前台进程,这样bash(Shell)不必等待进程结束就可以接受新的命令,启动新的进程。
  • 前台进程在运行的任何时候都可能收到ctrl+c产生的信号发生终止,所以说信号对于进程的控制流程来说是异步。

格外拓展:核心转储(core dump)

man  7  signal     功能:查看信号详细信息

从上面我们可以看出:SIGINT的默认处理动作是终止进程,SIGQUIT的默认处理动作是终止进程并且Core Dump,接下来我们来验证一下。

 再验证之前我们先来学习一个概念:Core Dump

在程序正常结束后,

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值