signal 信号机制

信号与中断的概念区分

信号机制常被称为“软件中断”,但是信号和中断其实没有联系。信号是在软件层面对中断机制的一种模拟。

中断机制面向的是处理器,处理器在受到中断信号(外部中断、快速中断。。。)时,查询中断向量表,执行中断服务程序,服务完成返回中断点。中断处理是在内核态执行的。

信号机制面向的是进程,进程之间约定好收到某个信号就做什么事情。(1)当一个进程想向另一个进程发送信号,或者(2)内核收到某些硬件中断或终端中断,有必要向进程发送信号告知有某种事件产生。进程在接收到信号的情况下,根据信号的处理设置(大部分信号可定制处理程序),去执行信号处理程序。信号处理程序是在用户态执行的。本质上,信号是一种进程间通信。

信号与中断的相似之处:

  • 都是异步的通信方式
  • 中断执行流,执行完服务程序就返回原来的断点
  • 信号和中断都是可屏蔽的

信号与中断的区别

  • 中断有优先级,而信号没有优先级,所有的信号都是平等的
  • 信号处理程序在用户态下执行,而中断服务程序在内核态下执行
  • 中断响应是及时的,而信号响应通常有较大的时间延迟

信号的接收与处理时机

信号是异步的,一个进程不可能等待信号的到来,也不知道信号是否会到来,何时到来。因此,信号的接收不可能是进程本身完成,而是由内核代理。当进程收到一个信号,内核就在进程的未决信号集上添加该信号。这就是信号的接收时机。相对简单。但是信号的处理时机并不是在信号被接收的时候。

信号的处理时机

参考:http://blog.csdn.net/icechenbing/article/details/7608710

内核处理一个进程收到的信号的时机是在进程从内核态返回用户态时。在一个进程在内核态下运行时,信号并不立即起作用,要等到返回用户态才处理。进程只有处理完信号才会返回用户态,进程在用户态下不会有未处理完的信号。

处理信号有三种类型:进程接收到信号后退出;进程忽略该信号;进程收到信号后执行用户设定用系统调用signal的函数。当进程接收到一个它忽略的信号时,进程丢弃该信号,就象没有收到该信号似的继续运行。如果进程收到一个要捕捉的信号,那么进程从内核态返回用户态时执行用户定义的函数。而且执行用户定义的函数的方法很巧妙,内核是在用户栈上创建一个新的层,该层中将返回地址的值设置成用户定义的处理函数的地址,这样进程从内核返回弹出栈顶时就返回到用户定义的函数处,从函数返回再弹出栈顶时,才返回原先进入内核的地方。这样做的原因是用户定义的处理函数不能且不允许在内核态下执行(如果用户定义的函数在内核态下运行的话,用户就可以获得任何权限)。

慢系统调用的中断和重启

慢系统调用(低速系统调用):可能一直阻塞的系统调用。

这里讨论的是信号的一种特殊的,影响编程的情况:阻塞情况下的系统调用。

Linux系统编程手册:如下场景

  • 为某个信号创建信号处理程序
  • 发起一个阻塞的系统调用
  • 系统调用在阻塞时,之前创建了信号处理程序的信号传递过来了,随即(注意)信号处理函数被执行,执行完返回用户程序。
    在这种情况下,该系统调用在没有正确执行完就被返回了。默认情况下,系统调用失败,errno被设置为EINTR。

非阻塞的系统调用是否会发生EINTR的调用失败情况?不会。

重启