6.1 信号

第6章 信号

信号是一种软件中断,用来处理异步事件。内核递送这些异步事件到某个进程,告诉进程某个特殊事件发生了。这些异步事件,可能来自硬件,比如访问了非法的内存地址,或者除以0了;可能来自用户的输入,比如shell终端上用户在键盘上敲击了Ctrl+C;还可能来自另一个进程,甚至有些来自进程自身。

信号的本质是一种进程间的通信,一个进程向另一个进程发送信号,内核至少传递了信号值这个字段。实际上,通信的内容不止是信号值。

**信号机制是Unix家族里一个古老的通信机制。**传统的信号机制有一些弊端,更为严重的是,信号处理函数的执行流和正常的执行流同时存在,给编程带来了很多的麻烦和困扰,一不小心就可能掉入陷阱。本章将会介绍信号的方方面面,包括传统信号的弊端,Linux对信号机制的改进,以及信号机制里面的陷阱,希望对读者能有所帮助。

6.1 信号的完整生命周期

前文提到过,信号的本质是一种进程间的通信

进程之间约定好:如果发生了某件事情T(trigger),就向目标进程(destination process)发送某特定信号X,而目标进程看到X,就意识到T事件发生了,目标进程就会执行相应的动作A(action)

接下来以配置文件改变为例,来描述整个过程。很多应用都有配置文件,如果配置文件发生改变,需要通知进程重新加载配置。

一般而言,程序会默认采用SIGHUP信号来通知目标进程重新加载配置文件。

目标进程首先约定,只要收到SIGHUP,就执行重新加载配置文件的动作。

这个行为称为信号的安装(installation),或者信号处理函数的注册。

**安装好了之后,因为信号是异步事件,不知道何时会发生,所以目标进程依然正常地干自己的事情。**某年某月的某一天,管理员突然改变了配置文件,想通知这个目标进程,于是就向目标进程发送了信号。他可能在终端执行了kill-SIGHUP命令,也可能调用了C的API,不管怎样,信号产生了。

这时候,Linux内核收到了产生的信号,然后就在目标进程的进程描述符里记录了一笔:收到信号SIGHUP一枚。

Linux内核会在适当的时机,将信号递送(deliver)给进程。

在内核收到信号,但是还没有递送给目标进程的这一段时间里,信号处于挂起状态,被称为挂起(pending)信号,也称为未决信号。

**内核将信号递送给进程,进程就会暂停当前的控制流,转而去执行信号处理函数。**这就是一个信号的完整生命周期。

一个典型的信号会按照上面所述的流程来处理,但是实际情况要复杂得多,还有很多场景需要考虑,比如:

  • 目标进程正在执行关键代码,不能被信号中断,需要阻塞某些信号,那么在这期间,信号就不允许被递送到进程,直到目标进程解除阻塞。

  • 内核发现同一个信号已经存在,那么它该如何处理这种重复的信号,排队还是丢弃?

  • 内核递送信号的时候,发现已有多个不同的信号被挂起,那它应该优先递送哪个信号?

  • 对于多线程的进程,如果向该进程发送信号,应该由哪个线程来负责响应?

这些问题,在接下来的章节中会逐一得到解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值