Linux中断处理与定时器

中断是现代操作系统中的重要功能之一。中断与硬件系统结合紧密,同时又对上层提供了良好的界面,是控制硬件相关的操作的重要手段。所以,在现代所有操作系统的编写中,都大量使用了中断处理机制。中断分两种,分别是由外部设备生成的硬件中断(比如键盘的敲击事件)和由软件程序所产生的软件中断(又称陷阱trap,比如进程所发送的信号时常引起中断)。Linux中同时支持Intel处理机的外部硬件中断和内部中断。
中断描述符(IDT)是建立在内存中的一个表,它的入口地址存放在一个中断入口寄存器中。这个表分两项,第一项是中断编号,它唯一标识一个中断;而与之相对应的是一个入口指针,该指针指向内存中相应中断处理程序的地址。当一个中断产生时,硬件会先查看处理机的相应中断允许位是否开放。如果该中断被允许,则将自动访问中断入口寄存器查找IDT的地址,然后访问IDT并根据中断号来寻找相应的表项,得到相应的中断处理程序入口指针,并调用此处理程序;如果该中断被屏蔽,则将对此中断视而不见。以上操作都是由硬件自动完成,而操作系统代码所需要完成的任务只是给出中断处理程序,并将其入口地址地址填入相应的IDT表项中去。当然,也有某些操作系统中IDT并不是定长的,只有在需要时,才在IDT表中加入一项。
Linux的IDT是定长的,它包含256个中断表项,即0~255。其中,0~31为Intel公司保留给异常处理程序的,其中断类型不能更改。在Linux的初始化阶段,对中断入口寄存器、中断控制器和IDT表进行了一系列初始化工作。
在中断响应时,为了避免重要操作出现嵌套,从而出现对系统造成破坏的可能行,操作系统规定要关闭中断允许位,直到中断处理程序中调用了开中断指令sti()为止。但是,如果一个中断的处理时间较长(比如一些硬件中断,可能会一直等待I/O),则中断将长时间关闭,这时将会失去对外部发来的其他中断的响应能力(也就是通常所说的“死机”状态)。
Linux中为了避免这样的事情发生,就将那些执行时间可能比较长的中断处理程序一分为二,称作top half和bottom half.其中,top half为一些重要的、与硬件设备紧密相关的程序,这些程序一定要关中断执行,而bottom half中为其余的一些处理程序,这些程序都时对内存进行操作,不怕被打断。当系统进入中断处理状态时,首先关中断执行top half。top的执行速度一般都很快。在top half结束后,将中断打开,继续执行bottom half中的处理程序,这时,新的中断又可以继续被截获。linux中提供了32种bottom half,每种都基本上对应一个设备驱动程序。
由于bottom half只有固定的32种,且其功能不能动态改变,使得她有时不能满足程序运行的需要。人们由此提出了新的机制,称作任务队列。任务队列基本上同bottom half相同,但它可以动态定义各种处理程序,将任意多个处理函数用队列的方式串起来,并在适当的时候顺序执行。
定时器(timer)时建立在时钟中断基础上的一种Linux定时服务机制。可以设置一个定时器在特定时间发送信号唤醒一个特定的进程。在Linux初始化时,设定8253的定时周期为10ms。由8253产生的时钟中断信号直接输入到第一块8259A的INT0,即IRQ0中。而IRQ0的中断处理程序在系统初始化时已经设定为timer_interrupt()调用。在timer_interrupt()调用中。实际上主要执行的是do_timer()调用,该调用设置一个bottom halg,编号为TIMER_BH。关于时钟的处理程序,主要是在这个bottom half中完成的。

你可能感兴趣的:(定时器,操作系统,寄存器,软件程序,处理机)