linux系统编程之信号(一):中断与信号

一,什么是中断?

1.中断的基本概念

中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被中断处继续执行或调度新的进程执行的过程。引发中断发生的事件被称为中断源。中断源向CPU发出的请求中断处理信号称为中断请求,而CPU收到中断请求后转到相应的事件处理程序称为中断响应。linux

在有些状况下,尽管产生了中断源和发出了中断请求,但CPU内部的处理器状态字PSW的中断容许位已被清除,从而不容许CPU响应中断。这种状况称为禁止中断。CPU禁止中断后只有等到PSW的中断容许位被从新设置后才能接收中断。禁止中断也称为关中断,PSW的中断容许位的设置也被称为开中断。开中断和关中断是为了保证某段程序执行的原子性。异步

还有一个比较经常使用的概念是中断屏蔽。中断屏蔽是指在中断请求产生以后,系统有选择地封锁一部分中断而容许另外一部分中断仍能获得响应。不过,有些中断请求是不能屏蔽甚至不能禁止的,也就是说,这些中断具备最高优先级,只要这些中断请求一旦提出,CPU必须当即响应。例如,电源掉电事件所引发的中断就是不可禁止和不可屏蔽的。函数

2.中断的分类与优先级

根据系统对中断处理的须要,操做系统通常对中断进行分类并对不一样的中断赋予不一样的处理优先级,以便在不一样的中断同时发生时,按轻重缓急进行处理。操作系统

根据中断源产生的条件,可把中断分为外中断和内中断。外中断是指来自处理器和内存外部的中断,包括I/0设备发出的I/O中断、外部信号中断(例如用户键人ESC键)。各类定时器引发的时钟中断以及调试程序中设置的断点等引发的调试中断等。外中断在狭义上通常被称为中断。.net

内中断主要指在处理器和内存内部产生的中断。内中断通常称为陷阱(trap)或异常。它包括程序运算引发的各类错误,如地址非法、校验错、页面失效、存取访问控制错、算术操做溢出、数据格式非法、除数为零、非法指令、用户程序执行特权指令、分时系统中的时间片中断以及从用户态到核心态的切换等都是陷阱的例子。设计

为了按中断源的轻重缓急处理响应中断,操做系统为不一样的中断赋予不一样的优先级。例如在UNIX系统中,外中断和陷阱的优先级共分为8级。为了禁止中断或屏蔽中断,CPU的处理器状态字PSW中也设有相应的优先级。若是中断源的优先级高于PSW的优先级,则CPU响应该中断源的请求;反之,CPU屏蔽该中断源的中断请求。unix

各中断源的优先级在系统设计时给定,在系统运行时是固定的。而处理器的优先级则根据执行状况由系统程序动态设定。调试

除了在优先级的设置方面有区别以外,中断和陷阱还有以下主要区别:blog

陷阱一般由处理器正在执行的现行指令引发,而中断则是由与现行指令无关的中断源引发的。陷阱处理程序提供的服务为当前进程所用,而中断处理程序提供的服务则不是为了当前进程的。继承

CPU执行完一条指令以后,下一条指令开始以前响应中断,而在一条指令执行中也能够响应陷阱。例如执行指令非法时,尽管被执行的非法指令不能执行结束,但CPU仍可对其进行处理。

3.软中断

软中断的概念主要来源于UNIX系统。软中断是对应于硬中断而言的。经过硬件产生相应的中断请求,称为硬中断。而软中断则否则,它是在通讯进程之间经过模拟硬中断而实现的一种通讯方式。中断源发出软中断信号后,CPU或者接收进程在“适当的时机”进行中断处理或者完成软中断信号所对应的功能。这里“适当的时机”,表示接收软中断信号的进程须等到该接收进程获得处理器以后才能进行。若是该接收进程是占据处理器的,那么,该接收进程在接收到软中断信号后将当即转去执行该软中断信号所对应的功能。

4.中断处理过程

一旦CPU响应中断,转人中断处理程序,系统就开始进行中断处理。下面对中断处理过程进行详细说明:

1)CPU检查响应中断的条件是否知足。CPU响应中断的条件是:有来自于中断源的中断请求、CPU容许中断。若是中断响应条件不知足,则中断处理没法进行。

2)若是CPU响应中断,则CPU关中断,使其进入不可再次响应中断的状态。

3)保存被中断进程现场。为了在中断处理结束后能使进程正确地返回到中断点,系统必须保存当前处理器状态字PSW和程序计数器PC等的值。这些值通常保存在特定堆栈或硬件寄存器中。

4)分析中断缘由,调用中断处理子程序。在多个中断请求同时发生时,处理优先级最高的中断源发出的中断请求。在系统中,为了处理上的方便,一般都是针对不一样的中断源编制有不一样的中断处理子程序(陷阱处理子程序)。这些子程序的人口地址(或陷阱指令的人口地址)存放在内存的特定单元中。再者,不一样的中断源也对应着不一样的处理器状态字PSW。这些不一样的PSW被放在相应的内存单元中,与中断处理子程序人口地址一块儿构成中断向量。显然,根据中断或陷阱的种类,系统可由中断向量表迅速地找到该中断响应的优先级、中断处理子程序(或陷阱指令)的入口地址和对应的PSW。

5)执行中断处理子程序。对陷阱来讲,在有些系统中则是经过陷阱指令向当前执行进程发出软中断信号后调用对应的处理子程序执行。

6)退出中断,恢复被中断进程的现场或调度新进程占据处理器。

7)开中断,CPU继续执行。

5.设备管理程序与中断方式

处理器的高速和输入输出设备低速之间的矛盾,是设备管理要解决的一个重要问题。为了提升总体效率,减小在程序直接控制方式中的CPU等待时间以及提升系统的并行工做效率,采用中断方式来控制输入输出设备和内存与CPU之间的数据传送,是颇有必要的。

在硬件结构上,这种方式要求CPU与输入输出设备(或控制器)之间有相应的中断请求线,并且在输入输出设备控制器的控制状态寄存器上有相应的中断容许位。

二,什么是信号?

一、信号及信号来源

信号本质

信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求能够说是同样的。信号是异步的,一个进程没必要经过任何操做来等待信号的到达,事实上,进程也不知道信号到底何时到达。

信号是进程间通讯机制中惟一的异步通讯机制,能够看做是异步通知,通知接收信号的进程有哪些事情发生了。信号机制通过POSIX实时扩展后,功能更增强大,除了基本通知功能外,还能够传递附加信息。

信号来源

信号事件的发生有两个来源:硬件来源(好比咱们按下了键盘或者其它硬件故障);软件来源,最经常使用发送信号的系统函数是kill, raise, alarm和setitimer以及sigqueue函数,软件来源还包括一些非法运算等操做。

二、信号的种类

能够从两个不一样的分类角度对信号进行分类:(1)可靠性方面:可靠信号与不可靠信号;(2)与时间的关系上:实时信号与非实时信号。在《Linux环境进程间通讯(一):管道及有名管道》的附1中列出了系统所支持的全部信号。

(一)、可靠信号与不可靠信号

"不可靠信号"

Linux信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,所以,把那些创建在早期机制上的信号叫作"不可靠信号",信号值小于SIGRTMIN(Red hat 7.2中,SIGRTMIN=32,SIGRTMAX=63)的信号都是不可靠信号。这就是"不可靠信号"的来源。它的主要问题是:

  • 进程每次处理信号后,就将对信号的响应设置为默认动做。在某些状况下,将致使对信号的错误处理;所以,用户若是不但愿这样的操做,那么就要在信号处理函数结尾再一次调用signal(),从新安装该信号。
  • 信号可能丢失,后面将对此详细阐述。
    所以,早期unix下的不可靠信号主要指的是进程可能对信号作出错误的反应以及信号可能丢失。

Linux支持不可靠信号,可是对不可靠信号机制作了改进:在调用完信号处理函数后,没必要从新调用该信号的安装函数(信号安装函数是在可靠机制上的实现)。所以,Linux下的不可靠信号问题主要指的是信号可能丢失。

"可靠信号"

随着时间的发展,实践证实了有必要对信号的原始机制加以改进和扩充。因此,后来出现的各类Unix版本分别在这方面进行了研究,力图实现"可靠信号"。因为原来定义的信号已有许多应用,很差再作改动,最终只好又新增长了一些信号,并在一开始就把它们定义为可靠信号,这些信号支持排队,不会丢失。同时,信号的发送和安装也出现了新版本:信号发送函数sigqueue()及信号安装函数sigaction()。POSIX.4对可靠信号机制作了标准化。可是,POSIX只对可靠信号机制应具备的功能以及信号机制的对外接口作了标准化,对信号机制的实现没有做具体的规定。

信号值位于SIGRTMIN和SIGRTMAX之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。Linux在支持新版本的信号安装函数sigation()以及信号发送函数sigqueue()的同时,仍然支持早期的signal()信号安装函数,支持信号发送函数kill()。

注:不要有这样的误解:由sigqueue()发送、sigaction安装的信号就是可靠的。事实上,可靠信号是指后来添加的新信号(信号值位于SIGRTMIN及SIGRTMAX之间);不可靠信号是信号值小于SIGRTMIN的信号。信号的可靠与不可靠只与信号值有关,与信号的发送及安装函数无关。目前linux中的signal()是经过sigation()函数实现的,所以,即便经过signal()安装的信号,在信号处理函数的结尾也没必要再调用一次信号安装函数。同时,由signal()安装的实时信号支持排队,一样不会丢失。

对于目前linux的两个信号安装函数:signal()及sigaction()来讲,它们都不能把SIGRTMIN之前的信号变成可靠信号(都不支持排队,仍有可能丢失,仍然是不可靠信号),并且对SIGRTMIN之后的信号都支持排队。这两个函数的最大区别在于,通过sigaction安装的信号都能传递信息给信号处理函数(对全部信号这一点都成立),而通过signal安装的信号却不能向信号处理函数传递信息。对于信号发送函数来讲也是同样的。

(二)、实时信号与非实时信号

早期Unix系统只定义了32种信号,Ret hat7.2支持64种信号,编号0-63(SIGRTMIN=31,SIGRTMAX=63),未来可能进一步增长,这须要获得内核的支持。前32种信号已经有了预约义值,每一个信号有了肯定的用途及含义,而且每种信号都有各自的缺省动做。如按键盘的CTRL ^C时,会产生SIGINT信号,对该信号的默认反应就是进程终止。后32个信号表示实时信号,等同于前面阐述的可靠信号。这保证了发送的多个实时信号都被接收。实时信号是POSIX标准的一部分,可用于应用进程。

非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号。

(三),信号名称

查看linux所支持的信号可用:kill –l

共64种:

QQ截图20130714104059

QQ截图20130714104217

QQ截图20130714104231

3、进程对信号的响应

进程能够经过三种方式来响应一个信号:(1)忽略信号,即对信号不作任何处理,其中,有两个信号不能忽略:SIGKILL及SIGSTOP;(2)捕捉信号。定义信号处理函数,当信号发生时,执行相应的处理函数;(3)执行缺省操做,Linux对每种信号都规定了默认操做,详细状况请参考[2]以及其它资料。注意,进程对实时信号的缺省反应是进程终止。

Linux究竟采用上述三种方式的哪个来响应信号,取决于传递给相应API函数的参数。

注:本文参考:http://blog.csdn.net/lmh12506/article/details/6681663

 http://blog.csdn.net/johnny710vip/article/details/6990514

相关文章
相关标签/搜索