您好,欢迎访问三七文档
4.1中断信号的作用4.2中断和异常4.3中断和异常处理程序的嵌套执行4.4初始化中断描述符表4.5异常处理4.6中断处理4.7软中断及tasklet4,8工作队列4.9从中断和异常返回中断:中断是一个能改变处理器执行顺序的事件。中断通常分为同步中断和异步中断。同步中断:当指令执行时由CPU控制单元产生的,只有在一条指令终止执行后CPU才会发出中断。异步中断:由其他硬件设备依照CPU时钟信号随机产生的。在Intel微处理器手册中,把同步和异步中断分别称为异常和中断。中断是由间隔定时器和I/O设备产生的,而异常是由程序的错误产生的,或者是由内核必须处理的异常条件产生的。中断信号的作用是提供一种特殊的方式使处理器转而去运行正常控制流之外的代码。当一个中断信号到达时,CPU必须停止它当前正在做的事情,并且切换到一个新的活动。为了做到这一点,就要在内核态堆栈保存程序计数器的当前值(即eip和cs寄存器的内容),并把与中断类型相关的一个地址放进程序计数器。中断处理与进程切换的区别:由中断或异常处理程序执行的代码不是一个进程。中断处理程序比一个进程要“light”(中断的上下文很少,建立或终止中断处理需要的时间很少)。中断:1)可屏蔽中断I/O设备发出的所有中断请求(IRQ)都产生可屏蔽中断,可屏蔽中断可以处于两种状态:屏蔽的或非屏蔽的,一个屏蔽的中断只要还是屏蔽的,控制单元就忽略它。2)非屏蔽中断只有几个危急事件(如硬件故障)才引起非屏蔽中断。非屏蔽中断总是由CPU辨认。异常:1)处理器探测异常当CPU执行指令时探测到的一个反常条件所产生的异常。可以分为3组:包括故障,陷阱和异常终止。这取决于CPU控制单元产生异常时候保存在内核态堆栈eip寄存器中的值。2)编程异常在编程者发出请求时发生。是由int或int3指令触发的;当into(检查溢出)和bound(检查地址出界)指令检查的条件不为真时,也引起编程异常。控制单元把编程异常作为陷阱来处理,编程异常通常也叫做软中断。编程异常有两种用途:执行系统调用和给调试程序通报一个特定的事件。每个能够发出中断请求的硬件设备控制器都有一条IRQ输出线,所有现有的IRQ线都与一个可编程中断控制器的输入引脚相连,可编程控制器执行以下动作:1.监视IRQ线,检查产生的信号。如果有两条或两条以上的IRQ线上产生信号,就选择引脚编号较小的IRQ线。2.如果一个引发信号出现在IRQ线上:a)把接收到的引发信号转换成对应的向量。b)把这个向量存放在中断控制器的一个I/O端口,从而允许CPU通过数据总线读此向量。c)把引发信号发送到处理器的INTR引脚,即产生一个中断。d)等待,直到CPU通过把这个中断信号写进可编程中断控制器的一个I/O端口来确认它,当这种情况发生时,清INTR线。3.返回到第一步。IRQ线是从0开始编号的,第一条IRQ线通常表示成IRQ0,与IRQn关联的Intel的缺省向量是n+32。可以有选择的禁止每条IRQ线,可以对PCI编程从而禁止IRQ。而有选择的激活/禁止IRQ线不同于可屏蔽中断的全局屏蔽/非屏蔽,当eflags寄存器的IF标志被清0时,由PIC发布的每个可屏蔽中断都由CPU暂时忽略,cli和sti汇编指令分别清除和设置该标志。目的:为了充分发挥多处理器体系结构的并行性,能够把中断传递给系统中的每个CPU。结构:每个CPU都含有一个本地APIC,每个本地APIC都有32位的寄存器,一个内部时钟,一个本地定时设备以及为本地APIC中断保留的两条额外的IRQ线LINT0和LINT1。所有本地APIC都连接到一个外部I/OAPIC,形成一个多APIC的系统。I/OAPIC的组成:一组24条IRQ线,一张24项的中断重定向表,可编程寄存器,以及通过APIC总线发送和接收APIC信息的一个信息单元。中断重定向表中的信息用于把每个外部IRQ信号转换为一条消息,然后通过APIC总线把消息发送给一个或多个本地APIC单元。来自外部硬件设备的中断请求以下面两种方式在可用CPU之间分发:1)静态分发IRQ信号传递给重定向表相应项中所列出的本地APIC。2)动态分发如果处理器正在执行最低优先级进程,IRQ信号就传递给这种处理器的本地APIC。如果两个或多个CPU共享最低优先级,就利用仲裁技术分配CPU。仲裁技术:在本地APIC的仲裁优先级寄存器中,给每一个CPU都分配一个0(最低)~15(最高)范围内的值。每当中断传递给一个CPU时,其相应的仲裁优先级就自动置为0,而其他每个CPU的仲裁优先级都增加1,当仲裁优先级寄存器大于15时,就把它置为获胜CPU的前一个仲裁优先级加1。因此,中断以轮转的方式在CPU之间分发,且具有相同的任务优先级。处理器间中断(IPI):除了在处理器之间分发中断外,多APIC系统还允许CPU产生处理器间中断。当一个CPU希望把中断发送给另一个CPU时,它就在自己本地APIC的中断指令寄存器(ICR)中存放这个中断向量和目标本地APIC的标识符。然后,通过APIC总线向目标本地APIC发送一条消息,从而向自己的CPU发出一条相应的中断。IPI被linux用来在CPU之间交换信息。80x86处理器发布了大约20种异常,内核必须为每种异常提供一个专门的异常处理程序,对于某些异常,CPU控制单元在开始执行异常处理前会产生一个硬件出错码,并且压入内核态堆栈。0Divideerror(故障)当一个程序试图执行整数被0除操作时产生1Debug(陷阱或故障)产生于设置eflags的TF标志或一条指令或操作数的地址落在一个活动debug寄存器的范围之内时。2未用为非屏蔽中断保留3Breakpoint(陷阱)由int3(断点)指令引起4Overflow(陷阱)当eflags的OF标志被设置时,into指令被执行。5Boundscheck(故障)对于有效地址范围之外的操作数,bound指令被执行。6Invalidopcode(故障)CPU执行单元检测到一个无效操作码。7Devicenotavailable(故障)随着cr0的TS标志被设置,ESCAPE、MMX或XMM指令被执行。8Doublefault(异常中止)正常情况下当CPU正试图为前一个异常调用处理程序时,同时又检测到一个异常,两个异常能被串行的处理,然而在少数情况下,处理器不能串行的处理它们,因而产生这种异常。9Coprocessorsegmentoverrun(异常中止)因外部的数学协处理器引起的问题。10InvalidTSS(故障)CPU试图让一个上下文切换到有无效TSS的进程。11Segmentnotpresent(故障)引用一个不存在的内存段。12Stacksegmentfault(故障)试图超过栈段界限的指令,或者ss标识的段不在内存。13Generalprotection(故障)违反了80x86保护模式下的保护规则之一。14Pagefault(故障)寻址的页不在内存,相应的页表项为空,或者违反了一种分页保护机制。15由Intel保留。16Floatingpointerror(故障)集成到CPU芯片中的浮点单元用信号通知一个错误情形,如数字溢出或被0除。17Alignmentcheck(故障)操作数的地址没有被正确的对齐18Machinecheck(异常中止)机器检查机制检测到一个CPU错误或总线错误。19SIMDfloatingpointexception(故障)集成到CPU芯片中的SSE或SSE2单元对浮点操作用信号通知一个错误情形。20~31这些值由Intel留作将来开发。中断描述符表是一个系统表,它与每一个中断或异常向量相联系,每一个向量在表中有相应的中断或异常处理程序的入口地址,内核在允许中断发生前,必须用lidt汇编指令初始化IDT。idtrCPU寄存器指定了IDT的线性基地址及其限制(最大长度),因此IDT可以位于内存的任何地方。IDT包含三种类型的描述符:1)任务门:当中断信号发生时,必须取代当前进程的那个进程的TSS选择符存放在任务门中。2)中断门:包含段选择符和中断或异常处理程序的段内偏移量。当控制权转移到一个适当的段时,处理器清IF标志,从而关闭将来会发生的可屏蔽中断。3)陷阱门:与中断门相似,只是控制权传递到一个适当的段时处理器不修改IF标志。当执行了一条指令后,cs和eip寄存器包含下一条将要执行指令的逻辑地址,在处理那条指令之前,控制单元会检查在运行前一条指令时是否已经发生了一个中断或异常,如果发生了一个中断或异常,控制单元执行以下操作:1.确定与中断或异常关联的向量i(0=i=255).2.读由idtr寄存器指向的IDT表中的第i项。3.从gdtr寄存器获得GDT的基地址,并在GDT中查找,以读取IDT表项中的选择符所标识的段描述符,这个描述符指定中断或异常处理程序所在段的基地址。4.确信中断是由授权的中断发生源发出的。首先将当前特权级CPL与段描述符的描述符特权级DPL比较,如果CPL小于DPL,就产生一个“Generalprotection”异常,因为中断处理程序的特权不能低于引起中断的程序的特权。对于编程异常则做进一步的安全检查:比较CPL与处于IDT中的门描述符的DPL,如果DPL小于CPL就产生一个“Generalprotection”异常。这最后一个检查可以避免用户应用程序访问特殊的陷阱门或中断门。5.检查是否发生了特权级的变化,也就是说,CPL是否不同于所选择的段描述符的DPL,如果是,控制单元必须开始使用与新的特权级相关的栈。6.如果故障已经发生,用引起异常的指令地址装载cs和eip寄存器,从而使得这条指令能再次被执行。7.在栈中保存eflags、cs及eip的内容。8.如果异常产生了一个硬件出错码,则将它保存在栈中。9.装载cs和eip寄存器,其值分别是IDT表中第i项门描述符的段选择符和偏移量字段。这些值给出了中断或者异常处理程序的第一条指令的逻辑地址。控制单元所执行的最后一步就是跳转到中断或异常的处理程序,即被选中处理程序的第一条指令。中断或异常处理完后,相应的处理程序必须产生一条iret指令,把控制权交给被中断的进程,这时控制单元执行以下操作:1.用保存在栈中的值装载cs、eip或eflags寄存器。如果一个硬件出错码曾被压入栈中,并且在eip内容的上面,那么执行iret指令前必须先弹出这个硬件出错码。2.检查处理程序的CPL是否等于cs中最低两位的值(这意味着被中断的进程与处理程序运行在同一特权级),如果是,iret终止执行,否则转入下一步。3.从栈中装载ss和esp寄存器,因此返回到与旧特权级相关的栈。4.检查ds、es、fs及gs段寄存器的内容,如果其中一个寄存器包含的选择符是一个段描述符,并且其DPL小于CPL,那么清相应的段寄存器。这是为了禁止用户态的程序(CPL=3)利用内核以前所用的段寄存器(DPL=0),如果不清这些寄存器,怀有恶意的用户态程序就可能利用它们来访问内核地址空间。每个中断或异常都会引起一个内核控制路径,或者说代表当前进程在内核态执行单独的指令序列。内核控制路径可以任意嵌套,一个中断程序可以被另一个中断程序“中断”,因此引起内核控制路径的嵌套执行。其结果是:对中断进行处理的内核控制路径的最后一部分指令并不总能使当前进程返回到用户态:如果嵌套深度大于1,这些指令将执行上次被打断的内核控制路径,此时的CPU依然运行在内核态。允许内核控制路径嵌套执行必须要求中断处理程序永不阻塞,即中断处理程序运行期间不能发生进程切换。在内核没有bug的情况下,大多数异常在在CPU处于用户态时发生。异常要么是由编程错误引起,要么是由调试程序触发,但是缺页异常发生在内核态。一个中断处理程序既可以抢占其他的中断处理程序,也可以抢占异常处理程序,相反,异常处理程序从不抢占中断处理程序。在内核态能触发的唯一异常就是缺页异常,但中断处理程序从不执行可以导致缺页的操作。在多处理器系统上,几个内核控制路径可以并发的执行,此外与异常相关的内核控制路径可以
本文标题:第四章 中断和异常
链接地址:https://www.777doc.com/doc-4024678 .html