【Linux】:信号的产生

信号

  • 一.前台进程和后台进程
    • 1.前台进程
    • 2。后台进程
    • 3.总结
  • 二.自定义信号动作接口
  • 三.信号的产生
    • 1.键盘组合键
    • 2.kill+信号+进程pid
    • 3.系统调用
      • 1.kill函数
      • 2.raise函数
      • 3.abort函数
  • 四.异常
  • 五.软件条件
  • 六.通过终端按键产生信号

【Linux】:信号的产生_第1张图片

一.前台进程和后台进程

1.前台进程

一个简单的代码演示

【Linux】:信号的产生_第2张图片

【Linux】:信号的产生_第3张图片

像这种程序在运行时,不能执行其他命令并且可以被ctrl+c终止的进程被称为前台进程。

2。后台进程

我们另外打开一个窗口,在另一个窗口运行程序。

【Linux】:信号的产生_第4张图片

这样在当前进程我们依然可以使用各种命令,但是该进程不能被ctrl+c终止,这样的进程被称为后台进程。

前台进程加个&也能变成后台进程。

【Linux】:信号的产生_第5张图片

可以通过进程的pid使用kill直接终止。

【Linux】:信号的产生_第6张图片

3.总结

Linux中,一次登陆中,一个终端,一般会配上一个bash,每一个登陆,只允许一个进程是前台进程,可以允许多个进程是后台进程。两者的本质区别就是谁来获取键盘输入。

为什么使用Ctrl c能将前台进程终止呢?就是因为前台进程能够读取到键盘输入,而ctrl c的本质就是发送一个2号信号。

【Linux】:信号的产生_第7张图片

我们把1到31号信号称为普通信号(产生后不必立即处理),后面的称为实时信号(一旦产生必须处理)。下面我们只对普通信号进行讨论。

信号的处理方式一般有三种:
1.默认处理 (例如2号信号的默认动作就是终止自己)
2.忽略信号
3.自定义方式(信号捕捉)。

二.自定义信号动作接口

【Linux】:信号的产生_第8张图片

第一个参数:指定要进行自定义的信号。

第二个参数:一个函数,要自定义的动作,该函数的返回值是void,参数表示该信号。

例如:2号信号默认是终止,接下来把它更改一下

【Linux】:信号的产生_第9张图片

【Linux】:信号的产生_第10张图片

注意:

  1. Ctrl-C 产生的信号只能发给前台进程。一个命令后面加个&可以放到后台运行,这样Shell不必等待进程结束就可以接受新的命令,启动新的进程。

  2. Shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接到像 Ctrl-C 这种控制键产生的信号。

  3. 前台进程在运行过程中用户随时可能按下 Ctrl-C 而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到 SIGINT 信号而终止,所以信号相对于进程的控制流程来说是异步(Asynchronous)的。

  4. 为什么操作系统能够读到ctrl+c呢?因为cpu实际上与键盘的一部分是直接相连的,当键盘开始输入时就会直接向CPU发送一个硬件中断,然后CPU就会让操作系统来读取键盘的输入,最后将输入内容进行相应的解读。

三.信号的产生

1.键盘组合键

上面已经介绍了ctrl+c—>信号2。这就是一种键盘组合键

ctrl+\ ->信号3

【Linux】:信号的产生_第11张图片

【Linux】:信号的产生_第12张图片

ctrl+z->19号

【Linux】:信号的产生_第13张图片

【Linux】:信号的产生_第14张图片

可以看到它并没有如我们预期那样打印,说明它是不能被捕捉的。

所以不是所有信号都能被捕捉。

2.kill+信号+进程pid

我们经常使用kill+进程pid终止程序,kill也常用来给进程发送信号,例如接下来给进程分别发送1,2,3信号。

【Linux】:信号的产生_第15张图片

在这里插入图片描述

【Linux】:信号的产生_第16张图片

3.系统调用

1.kill函数

系统调用函数也可以直接发送命令。

【Linux】:信号的产生_第17张图片

示例

【Linux】:信号的产生_第18张图片

另外创建一个死循环程序,用该程序终止。

【Linux】:信号的产生_第19张图片

在这里插入图片描述

2.raise函数

【Linux】:信号的产生_第20张图片

【Linux】:信号的产生_第21张图片

【Linux】:信号的产生_第22张图片

3.abort函数

【Linux】:信号的产生_第23张图片

它是引起一个正常的进程直接终止。给自己发一个6号信号。

【Linux】:信号的产生_第24张图片

四.异常

一个程序发生异常本质上是收到了信号。

各种异常

【Linux】:信号的产生_第25张图片

在这里插入图片描述

很明显出现了异常并且只打印出了上面一句话,后面并没有进行打印。实际上这是接收了8号信号。

【Linux】:信号的产生_第26张图片

在这里插入图片描述

这是一个最常见的段错误。它收到了11号信号。

原因

注意任何异常都只能给当前进程造成影响,不会波及其他进程。

为什么/0和野指针会导致进程崩溃呢?这是因为当运行这种代码时,会给进程发送异常信号,导致进程崩溃。

为什么/0和野指针会给进程发送信号呢?在CPU里有一个寄存器叫状态寄存器,在状态寄存器里有一个溢出标志位,当在做/0操作时,那么就直接溢出了,而溢出标志位就由0变为1,从而被操作系统识别,之后操作系统就能对信息做出处理。

那么野指针呢?在操作系统里有一个页表用来转换虚拟地址和物理地址,而野指针就是地址转换失败。一旦失败,就会把失败地址传回CPU寄存器里。

总结:操作系统怎么知道是溢出异常还是段错误呢?本质就是因为不同的报错对应的是不同CPU寄存器(硬件)的报错。

五.软件条件

异常只会由硬件产生吗?答案是当然不是。

还记得管道吗?一个进程进行写入,另一个进程进行读取。如果我们将读端关掉,那么写端也会关闭并且会发送13号信号。这其实就算一种软件异常。

alarm

【Linux】:信号的产生_第27张图片

【Linux】:信号的产生_第28张图片

【Linux】:信号的产生_第29张图片

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

【Linux】:信号的产生_第30张图片

【Linux】:信号的产生_第31张图片

一个进程在使用wait退出时会返回对应退出码(8-15位),而进程异常会收到退出信号(0-6位),第7位是coredum,它表示进程在终止的时候表示是core终止方式还是term终止方式。

【Linux】:信号的产生_第32张图片

core

在这里插入图片描述

term(以2号信号终止)

在这里插入图片描述

我们发现两者的core位都是0,怎么回事呢?其实是云服务器上的core功能默认是关闭的。

查看

【Linux】:信号的产生_第33张图片

开启core

【Linux】:信号的产生_第34张图片

在这里插入图片描述

在这之后形成了一个core文件。

【Linux】:信号的产生_第35张图片

core文件里会记录具体哪一行代码出现错误。直接使用gdb就可以调试。

信号发送其实本质上是给进程的PCB发。

【Linux】:信号的产生_第36张图片

你可能感兴趣的:(Linux系统,linux,运维,服务器)