信号

1.认识信号:

     信号: 用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。

我们通过终端命令查看所有信号

 

其中1-31我们称为普通信号

34-64是实时信号

 

2.谁发出了信号?信号是怎么表示的?

    其实信号是操作系统发出的,发向目标进程的。  与其说是操作系统发信号,不如说是写信号。

为什么这样说呢?

首先我们先了解一下信号的存储

信号的存储是在相应进程的PCB中的存储的,来看看信号在内核中的表示图

 

task-sturct就是我们熟悉的PCB,有个指针来维护三张位图,一个比特位代表一个信号

第一个block块表示该信号是否被屏蔽。

第二个pending代表的就是每个信号,用0和1标识是否产生该信号

第三个是一个函数指针数组

 

3.信号是如何产生的?

信号的产生有多种方法。

1.在终端按下某些组合键,比如ctrl+c 我们会发现进程在运行时按下ctrl+c会立即回到bash。

2.硬件异常产生信号,比如我们的除0操作,当CPU执行除0操作时会检测异常,然后通知内核,内核会发送信号给进程。

3.系统调用,一个进程调用了系统调用kill(2),这时候就可以发送信号给另一个进程,如果不明确指定信号则发送SIGTERM信号,该信号的默认处理动作时终止进程。

4.终端发送命令kill -n      n代表需要终止几号进程

5.软件条产生:比如SIGPIPE信号和SIGALRM信号

 

4.信号的处理

首先有四点认识

1.  处理信号的前提的认识信号。

2.接受一个信号,并不一定会立即处理,可能会在合适的时候处理。

3.信号的产生对进程是异步的。

4.信号如果无法立即处理,就需要记录下来。  需要注意的是,如果信号被阻塞,则在解除阻塞之前普通信号如果产生多次,只记录一次

 

信号处理的三种动作

1.执行默认动作

2.忽略默认动作

3.指定自定义动作

 

接下来我们看看信号的处理过程。

这里递达的意思就是实际执行信号的处理动作,就是信号处理的三种动作。

信号从产生到递达之间的状态叫做未决。

 

5.信号的阻塞

 

信号的阻塞就是屏蔽该信号,如果一个信号被阻塞,那么在他解除阻塞之前永远不会被递达。

要注意区别阻塞和忽略,阻塞是不会执行动作,不会递达的意思,而忽略是一种执行动作。

阻塞信号的方法就是修改block块。

还有一点需要注意的上面也提过就是

解除阻塞之前信号产生多次,普通信号只记录一次。

 

6.信号的捕捉

  信号的捕捉就是,如果信号的处理动作是用户自定义函数,在信号递达的时候调用这个函数,这就称为捕捉信号。

用一个简单的例子来说明

#include <iostream>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>

using namespace std;

void catch_signal(int sig)
{
   cout << "catch a signal is:" << sig << endl;
   exit(-1);
}

int main()
{
   signal(SIGFPE,catch_signal);
   int a = 10;
   int b = 0;
   int c = a / b;
   return 0;
}

运行程序我们发现除0了,但是程序并没有崩溃,因为我们捕捉了SIGFPE信号,一旦硬件异常内核发送信号给进程,我们通过捕捉该信号让他执行我们的自定义动作,而不是默认动作。这就是信号的捕捉。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值