中断实现的基本原理

发布者:TranquilDreamer最新更新时间:2018-11-27 来源: eefocus关键字:中断实现  基本原理 手机看文章 扫描二维码
随时随地手机看文章

前言:


中断是计算机发展中一个重要的技术,它的出现很大程度上解放了CPU,提高了CPU的执行效率。


在中断出现之前,CPU对IO采用的是轮询的方式进行服务,这使的CPU纠结在某一个IO上,一直在等待它的响应,如果它不响应,CPU就在原地一直的等下去。这样就导致了其他IO口也在等待CPU的服务,如果某个IO出现了important or emergency affairs,CPU也抽不出身去响应这个IO。


为了解决这个纠结的问题就------>出现了中断


中断控制的主要优点是只有在IO接口需要服务时才去响应它,使得CPU很淡定的做它自己的事情,只有IO口有需求的时候才去响应它。同时中断中也设计了中断优先级,来处理一些很紧急的事件。


一.中断的基本知识


1.中断的概念:


所谓中断,是指CPU在正常运行程序时,由于程序的预先安排或内外部事件,引起CPU中断正在运行的程序,而转到发生中断事件程序中。这些引起程序中断的事件称为中断源。


其实从 物理学的角度看,中断是一种电信号,由硬件设备产生,并直接送入中断控制器(如 8259A)的输入引脚上,然后再由中断控制器向处理器发送相应的信号。处理器一经检测到该信号,便中断自己当前正在处理的工作,转而去处理中断。此后, 处理器会通知 OS 已经产生中断。这样,OS 就可以对这个中断进行适当的处理。不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标识,这些值通常被称为中断请求线。


2.那么 当产生一个中断时,CPU是如何识别的呢?


在Intel X86中可以支持256中向量中断,为了使处理器能使别每种中断源,给它们进行了编号----->叫做中断向量


3.这些中断向量在Linux中是如何分配的:


编号0~31的向量对应于异常和非屏蔽中断


编号32~47的向量(即由IO设备引起的中断)分配给屏蔽中断。


编号48~255的向量用来标示软中断。Linux用其中的128或0x80来实现系统调用


非屏蔽中断的向量和异常的向量是固定的。 


4.异常和中断的区别:


1>异常:是指CPU内部出现的中断,即在CPU执行特定指令时出现的非法情况。同时异常也称为同步中断,因此只有在一条指令执行后才会发出中断 ,不可能在指令执行期间发生异常。


a.产生的原因:


程序的错误产生的(eg:除数为0)


内核必须处理的异常条件产生的(eg:缺页)


b.异常又分为故障和陷阱,它们都不使用中断控制器,也不能被屏蔽


C.X86处理处理器中大约有20中异常。Linux内核必须为每种异常提供一个专门的异常处理程序。


2>中断:也称为异步中断。因此它是由其他硬件设备依照 CPU 时钟信号随机产生,即意味着中断能在指令之间发生。


a.中断又分为外部可屏蔽中断(INTR)和外部非屏蔽中断(NMI)


所用I0设备产生的中断请求均引起可屏蔽中断


硬件故障引起的故障则产生非屏蔽中断。


John说明:


在CPU执行一个异常处理程序时,就不再响应其他异常和中断请求服务.那么如果此时发生了一个异常,CPU不能去响应它,又不能把它的信息丢失该怎么办呢?


这是就用到了堆栈,把所有的信息压入栈。等当前异常处理后,才从堆栈中取出信息再响应刚才的异常。(当产生多个非屏蔽中断时,CPU的处理方法同上)


二APIC和8259A 


中断的实现也需要硬件上的支持的,那么硬件上是如何支持中断的?


1.在X86计算机的 CPU 为中断只提供了两条外接引脚:NMI 和 INTR。


NMI 是不可屏蔽中断,它通常用于电源掉电和物理存储器奇偶校验;


INTR是可屏蔽中断,可以通过设置中断屏蔽位来进行中断屏蔽,它主要用于接受外部硬件的中断信号,这些信号由中断控制器传递给 CPU。


2.中断控制器


目前常见的中断控制器有可编程中断控制器8259A和高级可编程中断控制器(APIC)


1> 8259A


PIC(Programmable Interrupt Controller)是由两片 8259A 的外部芯片以“级联”的方式连接在一起。每个芯片可处理多达 8 个不同的 IRQ。因为从 PIC 的 INT 输出线连接到主 PIC 的 IRQ2 引脚,所以可用 IRQ 线的个数达到 15 个。


我们来看一个图:(进行看图说明)



a.第一级8259A是主中断控制器,它的第二个中断请求输入端与第二级8259A的中断输出端INT相连。


b.与中断控制器相连的每条线叫做中断线 。要使用中断线,就要进行中断线的申请,即IRQ。


那么这条线的名字是啥勒----》中断号。


IRQ线是从0开始顺序编号的,所以第一条IRQ线就是IRQ0。 


C.那么该中断号于我们上面所说的中断向量有什么关系呢


中断向量=中断号+32。


从此等式可以看出,第一个中断线(IR0)所对应的中中断向量是32.


由此可以得出:


(1)异常和非屏蔽向量是CPU 内部引起的中断


(2)向量32-47对应的是外部中断。


d.并不是每个设备都可以向中断线上发中断信号,只有对某一条确定的中断线拥有了控制权后,才可以向这条中断线上发送信号。


e. 8259A中还有一个很重要的寄存器->8位的中断屏蔽寄存器 ->这个寄存器的作用是屏蔽中断。


8位的中断屏蔽寄存每一位对应8259A中的一条中断线,如果要禁用某条中断线,则把中断屏蔽寄存器的相应位置1,要启用则置0。


J ohn哥说明:


屏蔽中断也可以从CPU的角度考虑,即清除eflag的中断标志位(IF),当IF位为0时禁止任何外部IO的中断请求,即关中断; 


f.共享中断(一个很重要的概念,后面程序中会涉及到它)


由于计算机的外部设备越来越多,所以15条中断线已经不够用了。中断线是很宝贵的资源,为了更好的利用它,只有当设备需要中断的时候才申请占用一个IRQ,并且为了让更多的设备使用中断采取了在申请IRQ时采用共享中断的方式。


2>高级可编程中断控制器(APIC)


先看图再说:


1.8259A 只适合单 CPU 的情况,为了充分挖掘 SMP 体系结构的并行性,能够把中断传递给系统中的每个 CPU 至关重要。基于此理由,Intel 引入了一种名为 I/O 高级可编程控 制器的新组件,来替代老式的 8259A 可编程中断控制器。该组件包含两大组成部分:一是“本地 APIC”,主要负责传递中断信号到指定的处理器;举例来说,一台具有三个处理器的机器,则它必须相对的要有三个本地 APIC。另外一个重要的部分是 I/O APIC,主要是收集来自 I/O 装置的 Interrupt 信号且在当那些装置需要中断时发送信号到本地 APIC,系统中最多可拥有 8 个 I/O APIC。 


2 .每个本地 APIC 都有 32 位的寄存器,一个内部时钟,一个本地定时设备以及为本地中断保留的两条额外的 IRQ 线 LINT0 和 LINT1。所有本地 APIC 都连接到 I/O APIC,形成一个多级 APIC 系统。


那么我们如何知道我们机子上使用的是那种中断控制器呢?


我们可以通过在终端出入命令:cat /proc/interrupts 来查看



a.若看到列表中有IO-APIC,说明您的系统正在使用 APIC。


若看到 XT-PIC,意味着您的系统正在使用 8259A 芯片 。


16位实地址模式的中断机制和32位保护模式的中断机制的最本质差别就是在保护模式心爱引入了中断描述表


在单处理器的系统中,第一列是中断号,第二列是CPU产生该中断的次数。最后一列是于这个中断相关的俄设备名字。这个名字是通过 参数devname提供给函数request_irq()(下篇文章会对它讲解)


三.中断描述表


1.为什么引入  


在实地址模式中,CPU把内存中从0开始的1kb空间作为一个中断向量表。表中的每个表项占四个字节,由两个字节的段地址和两个字节的偏移量组成,这样构成的地址就是相应中断处理程序的入口地址。


但是在保护模式下,由4个字节的表项构成的中断向量表已经不能满足要求了。在保护模式下,中断向量表中的表项由8个字节组成。此时他也有了新的名字---->中断描述表(Interrupt Descriptor Table,IDT),其中的每个表项叫做一个门描述符(great descriptor)


先来看图在说明:



1>DPL:段描述符的特权级


2>偏移量:入口函数地址的偏移量


3>P:表示段是否在内存中的标志


4>段选择符:入口函数所处代码段的选择符


5>D:标志位,1表示32位,0标示16位


6>xxx:3位门类型码


门类型符主要分为


a.中断门(interrupt gate):其类型码为110,中断门包含了一个中断或异常处理程序所在段的选择符和段内偏移量。


当控制权通过中断门进入中断处理程序时,处理器清IF标志即关中断这样就避免了中断嵌套的发生。


中断门中的DPL(请求特权级)为0,因此用户态中的进程不能访问中断门。所用的中断处理程序都由中断门激活,并全部限制在内核态。


b..陷阱门(tap gate)其类型码为111。它与中断门类似,唯一的区别是控制权通过陷阱门进入处理程序时保持IF标志位不变,即不关中断。


c.系统门(system gate):Linux内核特别设置的,用来让用户态的进程访问Intel的陷阱门。


系统门的DPL为3。系统调用就是通过系统门进入内核的。


2.在保护模式下,中断描述符表在内存的位置不再局限于从地址0开始的位置,而是可以放在内存的任何位置 。


1>为了实现这个功能--->CPU中设计了一个中断描述符表寄存器IDTR,用来存放中断描述符表在内存的起始位置。


2>中断描述表寄存器是一个48位的寄存器。它的低16为保存中断描述符表的大小,高32位保存中断描述表的基址。


3>看下图 :



我们知道了中断描述表的功能和基本设置后,那么系统是是在何时给它初始化以及是如何给它初始化的呢?


首先Linux内核在系统的初始化阶段对中断进行初始化,其中包括有:初始化可编程控制器8259A;将中断描述符表的起始地址装入IDTR中,并初始化表中的每一项。


3.中断的初始化


1>用户进程可以通过INT指令发出一个中断请求,其中断请求向量在0~255之间。


那么如何防止用户使用INT指令模拟非法的中断和异常?


此时DPL就起作用了->将DPL置为0就可以了。


2>但是,有时候必须让用户进程能够使用内核所提供的功能(比如系统调用)也就是从用户态进入内核态,此时就可以通过把中断门或陷阱门的DPL置为3来实现。


3>当计算机在实模式时,中断描述符表被初始化,并由BIOS使用。


but,在进入了Linux内核时,中断描述符表就被移到内存的另一个区域,并为进入保护模式进行预初始化:


用汇编指令LIDT对中断描述符表寄存器IDTR进行初始化,即把IDTR置为0,然后把中断描述符表IDT的起始地址装入IDTR。


4>中断描述表的初始化


a.第一次初始化:用setup_idt()函数填充中断描述符表中的256个表项,填充时使用一个空的中断处理程序。因为现在还是在初始化阶段,还没有任何中断处理程序,因此,用这个空的 中断处理程序 来填充每个表项。


b.第二此初始化:内核在启用分页功能后对IDT进行第二此初始化。


此时,使用实际的陷阱和中断处理程序替换这个空的处理程序。一旦这个过程完成后,对于每个异常,IDT都包含一个专门的陷阱门或系统门,而对每个外部中断,IDT都包含专门的中断门。

 

上面提到了对IDT的初始化,那么我们就递归深入下来看看系统是如何对IDT表项进行设置的


4.IDT表项的设置


IDT表项的设置是通过_set_gate()函数来实现的。


1>插入一个中断门


调用 set_intr_gate(n,addr)函数来实现


此函数的功能是在IDT的第n个表项插入一个中断门。门中的段选择符设置成内核代码的段选择符,偏移量设置为中断处理程序的地址addr,DPL字段设置为0.


分析下的形参:


n:表示在第几个表项中插入一个中断门。


addr:表示偏移量,此处偏移量设置为中断处理程序的地址addr.


现在我们迭代深入,看下它的内部是如何实现的 


  1. 330static inline void set_intr_gate(unsigned int n, void *addr)  

  2. 331{  

  3. 332        BUG_ON((unsigned)n > 0xFF);  

  4. 333        _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);  

  5. 334}  


我们可以看到它里面有封装了两个函数:我门继续迭代深入。


a.我们先来看看第一个函数的原型和功能:

 

  1. 19#if (_MIPS_ISA > _MIPS_ISA_MIPS1)  

  2.  20  

  3.  21static inline void  __BUG_ON(unsigned long condition)  

  4.  22{  

  5.  23        if (__builtin_constant_p(condition)) {  

  6.  24                if (condition)  

  7.  25                        BUG();  

  8.  26                else  

  9.  27                        return;  

  10.  28        }  

  11.  29        __asm__ __volatile__("tne $0, %0, %1"  

  12.  30                             : : "r" (condition), "i" (BRK_BUG));  

  13.  31}  

  14.  32  

  15.  33#define BUG_ON(C) __BUG_ON((unsigned long)(C))  

  16.  34  


(1)我们可以看到BUG_ON()函数是一函数宏,系统最终调用的是 __BUG_ON((unsigned long)(C))


函数:


__BUG_ON((unsigned long)(C))它的作用是判断n是否大于255,若大于255则出错。


此处的n表示在第n个表项中插入一个中断门(因为表项总共有255个,所以当n大于255时出错)。


(2) _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);


我们来分析下它的形参 :


第一个形参 n:表示在那个表项中插入一个中断门。


第二个形参 表示门描述符的类型,此处是插入一个中断门,所以它的形参是 GATE_INTERRUPT。


第三个形参表示偏移量,设置为中断处理程序的地址addr。


第四个形参表示DPL,我们可以看到给它传递的是0,即避免中断嵌套的发生。


第五个形参表示IST(Interrupt Stack Table)共 3 位,表达 IST1 - IST7 共 7 个 Stack pointer 


第六个形参表示门中的段选择符。此处设置成内核代码的段选择符。


我们还可以继续深入到 _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS)函数中看它到底是如何实现功能的,但由于篇幅有限。占时不在继续深入。


2.插入一个陷阱门


调用 set_trap_gate(n,addr)函数来实现。


此函数的功能是:在IDT的第n个表项中插入一个陷阱门。门中的段选择符设置成内核代码的段选择符,偏移量设置为异常处理程序的地址addr,DPL字段设置为0。


分析下的形参:


n:表示在第几个表项中插入一个中断门。


addr:表示偏移量,此处偏移量设置异常处理程序的地址addr.


现在我们迭代深入,看下它的内部是如何实现的


  1. 371static inline void set_trap_gate(unsigned int n, void *addr)  

  2. 372{  

  3. 373        BUG_ON((unsigned)n > 0xFF);  

  4. 374        _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);  

  5. 375}  

 

我们可以看到它内部同样封装了两个函数BUG_ON()和_set_gate()函数,它们的功能和实现方法都在上面具体分析过,再次不在分析。


3.插入一个系统门


调用 set_system_gate(n,addr)函数来实现。


此函数的功能是在IDT的第n个表项插入一个系统门。门中的段选择符设置成内核代码的段选择符,偏移量设置为异常理程序的地址addr,DPL字段设置为3.(所以,系统调用在用户态下可以通过INT 0X80顺利通过系统门。从而进入内核态)


分析形参:


n:表示在第几个表项中插入一个中断门。


addr:表示偏移量,此处偏移量设置为异常处理程序的地址addr.


现在我们迭代深入,看下它的内部是如何实现的


  1. 365static inline void set_system_trap_gate(unsigned int n, void *addr)  

  2. 366{  

  3. 367        BUG_ON((unsigned)n > 0xFF);  

  4. 368        _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);  

  5. 369}  

  6. 370  


我们可以看到它的内部实现还是和上面类似。唯一不同的是在_set_gate()函数中的两个参数不同。


一个参数是DPL被设置为03,还有一个是门类型的类型是GATE_TRAP


关键字:中断实现  基本原理 引用地址:中断实现的基本原理

上一篇:中断处理函数的注意事项
下一篇:中断和异常的处理

推荐阅读最新更新时间:2024-03-16 16:18

基本原理分别是什么?
常见的报警方式有6种 (1)指示灯或数码管显示出数据,以提醒操作人员注意。 (2)采用声、光及语音进行报警。其中,光效果通常取自发光二极管LED或其他光源器件;声效果可取自电铃、电笛、蜂鸣器、或音乐(语音)芯片等。 (3)合成语音报警。采用这种方式进行报警时,单片机应用系统将对语音信号进行采集、处理、合成和识别,使报警系统的功能更加完善,报警信息更加具体、生动、准确,直至给出报警对象的具体信息。 (4)图形、图像报警。这种系统设微型机控制的打印机或CRT显示器,使警卫人员在接受其他报警信号的同时,还能看到报警显示的画面或数据、文字,不但能将报警资料打印成文,而且可方便存档。 (5)具有控制功能的报警。这种报警系统具有控制
[单片机]
触摸屏基本原理
  触摸屏是计算机的输入设备,与能实现输入的键盘和能点击的鼠标不同,它能让用户通过触摸屏幕来进行选择。具有触摸屏的计算机的所需的储存空间不大,移动部分很少,而且能进行封装。触摸屏在使用起来 比键盘和鼠标更为直观,而且培训成本也很低。   所有的触摸屏有三类主要元件。处理用户的选择的传感器单元;和感知触摸并定位的控制器,以及由一个传送触摸信号到计算机操作系统的软件设备驱动。触摸屏传感器有五种技术:电阻技术、电容技术、红外线技术、声波技术或近场成像技术。   电阻触摸屏通常包括一张柔性顶层薄膜,以及一层玻璃作为基层,并由绝缘点隔离。每一层的内表面涂层均为透明的金属氧化物。电压在每层隔膜都有一个差值。按压顶层薄膜就会在各个电阻层之间
[工业控制]
EASYV1.00的基本原理
内存管理 ESAYV1.00的运行数据空间包括64K外部RAM+256字节CPURAM,将其分解为系统占用区、PLC资源区、用户嵌入数据区三部分。 1 系统占用区 系统占用区是EASYV1.00运行时,进行数据缓存、状态保持、系统堆栈等不对PLC及用户开设的域区。这部分数据区的初始化运行中的监视都由实时OS管理,PLC及用户嵌入程序不得非法侵入。 2 PLC资源区 梯形图语言管理的数据区包括位区、字区两部分。通常以元件形式体现。 a 输入继电器X:X0-X177 128点位型 b 输出继电器Y:Y0-Y177 128点位型 c 中间继电器M:M0-M1535 1536点位型 d 专用中间继电器M8000-M8255 256点
[模拟电子]
汽车防滑控制系统ABS/ASR基本原理及发展趋势
    1 ABS/ASR的基本原理      1.1 ABS的基本原理      ABS(Anti-lock Braking System,即防抱死制动系统)是在制动期间控制和监视汽车速度的电子控制系统。在汽车制动的过程中,它通过常规制动系统起作用,能够自动地控制车轮在旋转方向上的打滑,并把相应的滑移率控制在最佳范围之内,可提高汽车的主动安全性。      在汽车的制动过程中,使汽车制动而减速行驶的外力是路面作用于轮胎胎面上的地面制动力。但地面制动力取决于两个摩擦副的摩擦力:一是制动装置对车轮的摩擦力,即制动器制动力;另一个是轮胎与路面间的摩擦力,即地面附着力。只有当汽车有足够的制动器制动力及地面附着力时,才能获得足
[嵌入式]
天嵌开发板 TQ210 S5PV210 中断方式按键实现
中断在裸机开发中是非常重要的一项学习内容,之前学习过STM32的中断实现,是参考正点原子的代码,通过库函数的方式实现的,为了进一步深度理解其中的道理,此次通过天嵌的TQ210开发板实现中断方式。 具体功能为,LED正常闪烁,当按键被按下的时候,通过串口打印信息,提示按键被按下,此过程不影响LED正常闪烁。中断执行过程具体如下图: 根据示意图,可知道当有中断请求时,首先进行保护现场,然后跳到中断处理函数,执行中断处理函数当中的程序,最后进行恢复现场,程序继续运行。 通过查询开发板原理图得知,按键连接的为外部中断XEINT0,连接的芯片引脚为GPH0,具体细节如下图。 知道了硬件连接就可以进行代码编写了,具体流程
[单片机]
天嵌开发板 TQ210 S5PV210 <font color='red'>中断</font>方式按键<font color='red'>实现</font>
stm32f103按键中断实现方法
#include stm32f10x.h void LED_GPIO_Config() { /*定义一个GPIO_InitTypeDef类型的结构体*/ GPIO_InitTypeDef GPIO_InitStructure; /*开启GPIOB的外设时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /*选择要控制的GPIOB引脚*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; /*设置引脚模式为通用推挽输出*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode
[单片机]
Qi标准基本原理
Qi基于电磁感应原理进行输电。感应耦合电能传输系统的基本原理如右图所示。这个系统由发射器线圈L1和接收器线圈 L2组成,两个线圈共同构成一个电磁耦合感应器。发射器线圈所携带的交流电生成磁场,并通过感应使接收器线圈产生电压。这种电压可用于为移动设备供电或为电池充电。 电能传输效率取决于感应器之间的耦合(k)和它们的品质(Q)。(见优值因数) 耦合不仅与两个感应器(z)之间的距离以及相对大小(D2 /D)有关,还与线圈的形状和它们之间的角度有关(图上无显示)。 系统概述 Qi 无线充电系统由基站和移动设备组成。基站包含一个或多个发射器,发射器将提供用以接收的能量。移动设备包含一个接收器用来提供电能给负载(如电池),接收器还将为发
[电源管理]
Qi标准<font color='red'>基本原理</font>
stm32 外部中断库函数实现全程分析
前题:   闭门造车,两周了,经过各种的思考和求问,反复阅读了 M3权威指南 和 stm32不完全手册 的相关章节,以及开发板厂商的实验例程,对stm32这块中断终有所悟,是以记之。   至于中断的什么优先级,什么优先级分组,使能之类的原理,就不再赘述。这里主要是记载以下如何使用中断,以及中断配置函数的实现过程,其中并叙述我曾经的疑惑和感悟。   我的开发板里的中断例程是用按键控制一个灯亮和灭的两个状态。   这个例程的实现过程如下描述: 第一步,将一个I/O口配置成中断输入模式。      这里需要注意的是,GPIO本身是没有中断功能神马的。如果硬要使他产生中断输入方式,就得将相应的端口映射到相应的外部事件上去。而
[单片机]
stm32 外部<font color='red'>中断</font>库函数<font color='red'>实现</font>全程分析
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved