0
点赞
收藏
分享

微信扫一扫

Linux进程信号

江南北 2022-03-27 阅读 46
linux

目录

一、信号的概念

二、信号的产生

1.硬件产生(键盘敲)

2.软件产生(函数代码)

 3.扩展知识

查看崩溃程序收到的信号的步骤:

 常见的几种进程崩溃的原因:

三、信号的种类

kill -l 可以罗列信号,总共有62个信号:

信号分为两种:

四、信号的处理方式

操作系统对信号的处理方式:(man 7 signal)

 1.默认处理方式:(SIG_DEF),操作系统当中已经定义信号的处理方式了

2.忽略处理方式:SIG_IGN,该信号为忽略处理(僵尸进程产生的原因)

3.自定义处理方式:程序员可以更改信号的处理方式,定义一个函数,当进程收到该信号的时候,调用程序员自己写的函数。

五、信号的注册

基础概念

信号的注册:

实时信号和非实时信号注册的区别:

六、信号的注销

非可靠信号

可靠信号:

七、信号的自定义处理方式

signal函数:

sigaction函数:

二者进行一个比较:

代码测试:

signal函数与sigaction函数原理图:

八、信号的捕捉流程

1.流程图:

2.信号的处理时机:当从内核态切换回用户态的时候,会调用do_signal函数处理信号

3.处理信号的时候,不同的处理方式

 4.常见的进入到内核的方式:

九、信号的阻塞

1.概念

2.内核代码:

3.加上信号阻塞之后,理解信号的处理:

4.接口

 原理解析:

设置阻塞:

设置非阻塞:

十、其他扩展内容

1.父子进程+进程等待+自定义处理方式

2.volatile关键字


一、信号的概念

信号是一个软中断,只是告诉有这样一个信号,但是这个信号具体怎么处理,什么时候处理由进程决定的,所以是软中断。

举个不恰当的例子:看到了红灯你可以选择走也可以选择不走,绿灯你也可以选则走,也可以选择不走。

二、信号的产生

1.硬件产生(键盘敲)

例如:

ctrl + c:2号信号 SIGINT(退出一个进程)

ctr + z:20号信号 SIGTSTP(终止一个进程),可以通过ps aus | grep “进程名”查看(运行着的进程)进程状态

ctr + | :3号信号SIGQUIT(退出一个进程)

除此之外我们还可以通过kill命令向进程发送信号,格式:kill [信号值] [pid]

2.软件产生(函数代码)

kill函数:注:以后的函数都使用图片表示,方便查看

raise函数:

 3.扩展知识

查看崩溃程序收到的信号的步骤:

>>1.我们先将生成coredump文件的大小设置为unlimited

>>2.我们在生成可执行程序的命令后加上-g选项,生成dubeg文件

 

>>3.使用gdb调试生成的coredump文件

 常见的几种进程崩溃的原因:

1.解引用空指针(11号信号)

2.内存访问越界(11号信号)

3.除0(8号信号)

4.double free(6号信号)

三、信号的种类

kill -l 可以罗列信号,总共有62个信号:

信号分为两种:

非实时信号(非可靠信号):信号可能会丢失,1~31号

实时信号(可靠信号):信号不会丢失33~64号

四、信号的处理方式

操作系统对信号的处理方式:(man 7 signal)

 1.默认处理方式:(SIG_DEF),操作系统当中已经定义信号的处理方式了

》》2号信号---终止进程

》》11号信号---终止进程,并且产生核心转储文件

2.忽略处理方式:SIG_IGN,该信号为忽略处理(僵尸进程产生的原因)

进程收到忽略处理的信号后,是不进行处理的。

例如SIGCHLD信号,子进程先于父进程退出,向父进程发送SIGCHLD,而父进程接收到这个信号后是忽略处理的,导致了父进程并没有回收子进程的退出状态信息,从而子进程变成了僵尸进程。

3.自定义处理方式:程序员可以更改信号的处理方式,定义一个函数,当进程收到该信号的时候,调用程序员自己写的函数。

五、信号的注册

基础概念

一个进程收到一个信号,这个过程称之为注册,信号的注册和注销是两个独立的过程。

信号的注册:

位图更改为1,添加sigqueue节点到sigqueue队列

1.信号注册的时候会将信号对应的比特位从0修改为1,表示当前进程收到了信号。

2.在sigqueue队列当中添加一个sigqueue节点,队列在操作系统内核当中本质上就是一个双向链表(先进先出的特性)

实时信号和非实时信号注册的区别:

非实时信号:多次注册同一个信号的时候,只会修改一次位图(信号没有被注销的前提下),而且只会添加一个sigqueue节点

实时信号:多次注册的时候同样只会修改一次位图,但是注册几次就会添加几次的sigqueue节点。

信号注册的时候

六、信号的注销

非可靠信号

1.将信号对戏那个的sig位图当中的比特位设置为0

2.将对应信号的sigqueue节点进行出队操作

可靠信号:

1.将对应信号的sigqueue节点进行出队操作

2.判断sigqueue队列当中是否还有相同的sigqueue节点,有的话就不修改位图,否则,将信号对戏那个的sig位图当中的比特位设置为0

七、信号的自定义处理方式

1.信号的自定义处理方式,就是让程序员自己定义某一个信号的处理方式

2.对应的自定义处理的函数

signal函数:

sigaction函数:

二者进行一个比较:

signal函数修改的其实是struct sigaction结构体中的(*sa_handler)(int)这个函数指针的指向为我们的自定义方式---》修改的是结构体的一个成员

sigaction函数修改的是整个struct sigaction结构体。---》修改的是整个结构体

代码测试:

signal函数与sigaction函数原理图:

八、信号的捕捉流程

1.流程图:

2.信号的处理时机:当从内核态切换回用户态的时候,会调用do_signal函数处理信号

有:就处理信号(信号的处理方式(默认、忽略、自定义))

分为三个步骤:1.判断当前信号是否被阻塞

                          2.信号的注销过程

                          3.调用信号的处理方式函数

没有:就直接返回用户态

3.处理信号的时候,不同的处理方式

默认,忽略:直接在内核就处理结束

自定义处理:调用程序员自定义的处理函数进行处理

  • 执行用户自定义的处理函数(用户空间)
  • 调用sigreturn()再次回到操作系统内核(内核空间)
  • 再次调用会调用do_signal函数处理信号
  • 调用sys_sigreturn函数回到用户空间,继续执行代码

 4.常见的进入到内核的方式:

调用系统调用函数,内存访问越界,访问空指针,调用库函数

九、信号的阻塞

1.概念

信号的注册是信号的注册,信号的阻塞是信号的阻塞。信号的阻塞并不会干扰信号的注册,而是说进程收到这个信号之后,由于阻塞,暂时不处理该信号。阻塞并不是说不处理该信号,而是等该信号不阻塞了之后,再进行处理。

2.内核代码:

3.加上信号阻塞之后,理解信号的处理:

  • 进入内核,返回之前,会调用do_signal函数处理信号
  • 有信号要处理,则先判断该信号是否阻塞,如果没阻塞,则处理信号,如果阻塞,则不处理

4.接口

 

 原理解析:

设置阻塞:

新的位图与旧的位图相或

设置非阻塞:

1.将新的位图按位取反

2.与旧的位图相与

 

 利用阻塞性质验证可靠信号和非可靠信号在sigqueue中的注册方式的不同:

十、其他扩展内容

1.父子进程+进程等待+自定义处理方式

2.volatile关键字

作用:保存内存可见性

每次CPU要计算的数据都是从内存当中获取,拒绝编译时的优化方案(从寄存器当中获取)

gcc/g++的编译器选项“-00,-01,-02,-03”,优化时级别越来越高。(理解优化级别越高,程序执行的越快)

举报

相关推荐

0 条评论