Linux的进程信号

1、信号的概念

信号是进程之间事件异步通知的一种方式,属于软中断。
如:其实我们平常写出了解引用空指针、数组越界会发生段错误,这些其实在内核都是看做信号来处理的。
为什么是异步的:shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接到像 ctrl-c 这种控制键产生的信号。前台进程在运行过程中用户随时可能按下 ctrl-c 而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到 SIGINT 信号而终止,所以信号相对于进程的控制流程来说是异步的。

2、信号的产生

通过终端按键
如当某程序在前台执行的时候,键盘按下ctrl+c便可以中止该进程

通过系统调用
如当一个程序在后台执行的时候,我们在shell命令行输入kill 7789(7789是这个进程的pid),则会强杀这个进程;或者输入kill -SIGSEGV 7789(SIGSEGV是段错误信号),虽然这个进程本身的逻辑是没有错误的,但是这里直接系统调用发给这个进程,则也会触发这个信号

由软件条件产生信号
如在源代码开头写入系统函数alarm(5),当这个程序执行后5秒便会给进程发一个SIGALRM信号,而该信号的默认处理动作就是中止当前进程

异常产生信号
如在程序里有除以0、当前进程访问了非法地址等等,这些一发生就会产生对应的信号,具体处理的行为要依对应的信号处理函数

3、操作系统是如何管理信号的

3.1 信号相关的定义

1、实际执行信号的处理动作称为信号递达(Delivery)。
2、信号从产生到递达之间的状态,称为信号未决(Pending)。
3、进程可以选择阻塞 (Block)某个信号。
4、被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。
注意:阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

3.2 PCB中有关信号的结构

PCB是每个进程承载各种数据的结构体,其中信号相关的就包括:pending位图、blocking位图、struct sighand_struct* sighand结构体指针。
pending未决位图:那个标志被置1,就表示这个进程收到了这个标志的信号
blocking阻塞位图:那个标志被置1,则对应信号被阻塞
struct sighand_struct sighand*:这个结构体指针指向sturct sighand_struct结构体;sturct sighand_struct结构体里存放struct sigaction []数组,而这个数组的数组下标就是信号的标号(和文件描述符类似);然后struct sigaction []数组里每一个元素都对应一个结构体,结构体里面都有这个信号所对应的处理函数。
在这里插入图片描述

3.3 信号的处理流程

信号刚产生,会给pending未决位图里的对应位置置1,然后等到从用户态到内核态时判断:blocking阻塞位图对应的位图是否是1,是:则忽略该信号,但是并不会将pending位图的对应位置变为0,因为之后可能还会给blocking置为0,如果给阻塞位图置为0了,那下次进入内核态的时候会处理这个信号;否:按照自己定义的处理函数/系统默认的处理函数去执行

4、信号的种类

信号分为两种:常规信号和实时信号。

常规信号:编号34号以前的都是常规信号。产生常规信号的时候,把pending置1,把信号节点放入信号队列,再来同样的信号时候,如果pending是1,则不会再去放入队列。处理的时候,去信号队列取出一个,pending置0,处理信号。

实时信号:编号34号以后的都是实时信号。产生实时信号的时候,把pending置1,把信号放入信号队列,再来同样的信号时候,如果pending是1,则再放一个信号节点放到队列。处理的时候,去信号队列取出一个,再看看队列是否还有这个信号节点,没有:pending置1,处理信号;有:处理信号,pending不变

区别:如果在一段时间(进程还没去处理信号的时间)发送多个常规信号,操作系统只会处理一次;而发送多个实时信号,操作系统会处理多次

我们可以通过kill -l查看各个信号的信息
在这里插入图片描述

5、信号的捕捉

信号的捕捉就是:当产生信号的时候,让操作系统按照我们设定的函数去处理这个信号。

信号捕捉函数:signal(2,handler)。其中2是编号为2的信号,handler是一个处理函数。这个函数是把2的默认处理函数更改为handler。

在这里插入图片描述
捕捉步骤
1、先用signal()函数设定好要处理的信号的函数。
2、执行程序后,当前正在执行main函数,这时候发生了中断、异常、系统调用等进入了内核态。
3、内核先处理这个中断、异常、系统调用,然后会判断PCB里的pending位图是否有哪个信号被置为1,并且对应的blocking位图为0;如果有,则会调用系统调用do_signal。
4、do_signal会判断当前的处理函数是否是自定义的,是的话则返回用户态去执行对应的自定义信号处理函数sighandler(注意:sighandler和main函数不在一个堆栈空间)
5、当对应的自定义信号处理函数sighandler执行完成后会调用sig_return再次进入内核
6、进入内核后会继续判断是否还有信号需要处理,如果有则:再进入do_signal然后去执行对应的处理函数;如果没有则会返回用户态,继续执行刚刚执行到的逻辑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值