精华内容
下载资源
问答
  • 有另一个优先级更高的中断提出中断请求,这时会暂时终止当前正在执行的级别较低的中断源的服务程序,去处理级别更高的中断源,待处理完毕,再返回到被中断了的中断服务程序继续执行,这个过程就是中断嵌套 ...

    中断向量:

    中断服务程序的入口地址

    中断嵌套

    是指中断系统正在执行一个中断服务时,有另一个优先级更高的中断提出中断请求,这时会暂时终止当前正在执行的级别较低的中断源的服务程序,去处理级别更高的中断源,待处理完毕,再返回到被中断了的中断服务程序继续执行,这个过程就是中断嵌套

    链接:https://www.nowcoder.com/questionTerminal/2e85847c06684c2faeaf8728f72e5045?toCommentId=426573

    保护现场

    主程序和中断服务子程序都要使用CPU内部寄存器等资源,为使中断处理程序不破坏主程序中寄存器的内容,应先将断点处各寄存器的内容压入堆栈保护起来,再进入的中断中断返回过程如下:首先恢复原保留寄存器的内容和标志位的状态,这称为恢复现场

     

    中断返回:

    由用户编程完成。然后,再加返回指令RETI,RETI指令的功能是恢复PC值,使CPU返回断点,这称为恢复断点。恢复现场和断点后,CPU将继续执行原主程序,中断响应过程到此为止处理。现场保护是由用户使用PUSH指令来实现的。

    恢复现场

    当中断处理完毕后,用户通过POP指令将保存在堆栈中的各个寄存器的内容弹出,即恢复主程序断点处寄存器的原值。

     

    中断服务

    中断服务是执行中断的主体部分,不同的中断请求,有各自不同的中断服务内容,需要根据中断源所要完成的功能,事先编写相应的中断服务子程序存入内存,等待中断请求响应后调用执行

    https://zhidao.baidu.com/question/552583801.html

    展开全文
  • Linux内核中断嵌套

    千次阅读 2016-10-30 14:47:36
    为了支持中断嵌套执行,Linux内核在进入中断服务程序之前会将硬中断开启,运行完中断服务程序之后再将硬中断关闭,在这期间硬件中断时可以被抢占的,而软中断执行过程中硬件中断始终是开启的。如果没

    假设读者对Linux内核的中断一定的理解,下面来介绍Linux内核的中断嵌套和抢占规则。
    1 中断运行过程中的开关情况
    在进入硬中断的时候,CPU会自动将硬中断功能关闭;进入软件中断的时候不会关闭中断功能。为了支持中断的嵌套执行,Linux内核在进入中断服务程序之前会将硬中断开启,运行完中断服务程序之后再将硬中断关闭,在这期间硬件中断是可以被抢占的,而软中断执行过程中硬件中断始终是开启的。如果没有特殊说明,下面的中断都指硬中断。关闭中断是硬件自动完成的,为了实现中断的嵌套,需要人为的打开中断。中断发生后会进行多次函数跳转,最终会进入到真正的中断处理函数handle_IRQ_event(),在该函数里执行各设备的中断服务程序。函数定义如下:

    irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
    {
        irqreturn_t ret, retval = IRQ_NONE;
        unsigned int status = 0;
    
        handle_dynamic_tick(action);
    
        if (!(action->flags & IRQF_DISABLED))
            local_irq_enable_in_hardirq();//开中断
    
        do {
            ret = action->handler(irq, action->dev_id);
            if (ret == IRQ_HANDLED)
                status |= action->flags;
            retval |= ret;
            action = action->next;
        } while (action);
    
        if (status & IRQF_SAMPLE_RANDOM)
            add_interrupt_randomness(irq);
        local_irq_disable();//关中断
    
        return retval;
    }

    while循环是依次执行中断向量上的所有设备的中断服务程序,由各设备中断服务程序对中断源进行识别。可以看到在执行中断服务程序之前执行local_irq_enable_in_hardirq()将中断打开,在执行完服务程序之后执行local_irq_disable()将中断再次关闭。也就是说在执行具体设备的中断服务程序时是允许中断发生的,也就是中断嵌套。
    2 中断的抢占规则
    硬件中断可以抢占软件中断,硬件中断可以被更高优先级的硬件中断抢占,软件中断不能抢占别的中断。内核保证中断和异常执行的过程中不会发生新的异常,实际上内核态能触发的异常只有缺页异常,但是中断处理程序不执行会引发缺页异常的操作。
    3 中断的嵌套
    中断的抢占是可以嵌套的,导致内核控制路径的嵌套执行。中断执行过程中不允许睡眠和进程切换(一般情况下睡眠都会导致进程切换),而且对中断的抢占只能发生在中断服务程序执行期间,只有这期间中断服务才是开启的。同时,同一中断通道不允许嵌套执行,即同一中断向量上的中断服务程序至多只能有一个出现在所有CPU的中断控制路径中。
    4 软中断,tasklet和工作队列
    软中断不同于软件中断,软中断发生的时机是从中断、调用或者异常返回用户空间之前,按照软中断在结构数组中定义的顺序依次执行。同一个软中断可以在不同CPU上并发执行。软中断执行过程中也不允许睡眠和进程切换。
    tasklet基于软中断实现,在软中断结构数组中占用两项。当软中断执行到这两项时就会跳转到tasklet函数入口处,依次执行队列中的tasklet函数。同一个tasklet不能在不同CPU上并发执行,但是不同tasklet可以在不同CPU上执行。tasklet始终运行在被初始提交的同一处理器上。
    工作队列实际上是使用内核线程来实现的,工作队列允许睡眠,可以当做普通的内核线程来看待,他有自己的上下文环境。

    展开全文
  • 在linux内核里,如果驱动在申请注册中断的时候没有特别的指定,do_irq在做中断响应的时候,是开启中断的,如果在驱动的中断处理函数正在执行过程中,出现同一设备的中断或者不同设备的中断,这时候新的中断会被...
  • 关于中断嵌套: 在linux内核里,如果驱动在申请注册中断的时候没有特别的指定,do_irq在做中断响应的时候,是开启中断的,如果在驱动的中断处理函数正在执行过程中,出现同一设备的中断或者不同设备的中断,...

    关于中断嵌套:

    在linux内核里,如果驱动在申请注册中断的时候没有特别的指定,do_irq在做中断响应的时候,是开启中断的,如果在驱动的中断处理函数正在执行的过程中,出现同一设备的中断或者不同设备的中断,这时候新的中断会被立即处理,还是被pending,等当前中断处理完成后,再做处理。
    在2.4和2.6内核里,关于这一块是否有什么不同。

    一般申请中断的时候都允许开中断,即不使用SA_INTERRUPT标志。如果允许共享则加上 SA_SHIRQ,如果可以为内核熵池提供熵值(譬如你写的驱动是ide之类的驱动),则再加上 SA_SAMPLE_RANDOM标志。这是普通的中断请求过程。对于这种一般情况,只要发生中断,就可以抢占内核,即使内核正在执行其他中断函数。这里有两点说明:一是因为linux不支持 中断优先级,因此任何中断都可以抢占其他中断,但是同种类型的中断(即定义使用同一个 中断线的中断)不会发生抢占,他们会在执行本类型中断的时候依次被调用执行。二是所谓 “只要发生中断,就可以抢占内核”这句是有一定限制的,因为当中断发生的时候系统由中断门 进入时自动关中断(对于x86平台就是将eflags寄存器的if位置为0),只有当中断函数被执行 (handle_IRQ_event)的过程中开中断之后才能有抢占。 对于同种类型的中断,由于其使用同样的idt表项,通过其状态标志(IRQ_PENDING和 IRQ_INPROGRESS)可以防止同种类型的中断函数执行(注意:是防止handle_IRQ_event被重入, 而不是防止do_IRQ函数被重入),对于不同的中断,则可以自由的嵌套。因此,所谓中断嵌套, 对于不同的中断是可以自由嵌套的,而对于同种类型的中断,是不可以嵌套执行的。 
    以下简单解释一下如何利用状态标志来防止同种类型中断的重入:
    当某种类型的中断第一次发生时,首先其idt表项的状态位上被赋予IRQ_PENDING标志,表示有待处理。 然后将中断处理函数action置为null,然后由于其状态没有IRQ_INPROGRESS标志(第一次),故将其状态置上IRQ_INPROGRESS并去处IRQ_PENDING标志,同时将action赋予相应的中断处理函数指针(这里是一个重点,linux很巧妙的用法,随后说明)。这样,后面就可以顺利执行handle_IRQ_event进行中断处理,当在handle_IRQ_event中开中断后,如果有同种类型的中断发生,则再次进入do_IRQ函数,然后其状态位上加上IRQ_PENDING标志,但是由于前一次中断处理中加上的IRQ_INPROGRESS没有被清除,因此这里无法清除IRQ_PENDING标志,因此action还是为null,这样就无法再次执行handle_IRQ_event函数。从而退出本次中断处理,返回上一次的中断处理函数中,即继续执行handle_IRQ_event函数。当handle_IRQ_event返回时检查IRQ_PENDING标志,发现存在这个标志,说明handle_IRQ_event执行过程中被中断过,存在未处理的同类中断,因此再次循环执行handle_IRQ_event函数。直到不存在IRQ_PENDING标志为止。

    2.4和2.6的差别,就我来看,主要是在2.6中一进入do_IRQ,多了一个关闭内核抢占的动作,同时在处理中多了一种对IRQ_PER_CPU类型的中断的处理,其他没有什么太大的改变。这类IRQ_PER_CPU的中断主要用在smp环境下将中断绑定在某一个指定的cpu上。例如arch/ppc/syslib/open_pic.c中的openpic_init中初始化ipi中断的时候。

           其实简单的说,中断可以嵌套,但是同种类型的中断是不可以嵌套的,因为在IRQ上发生中断,在中断响应的过程中,这个IRQ是屏蔽的,也就是这个IRQ的中断是不能被发现的。

           同时在内核的临界区内,中断是被禁止的

    关于do_IRQ可能会丢失中断请求:

    do_IRQ函数是通过在执行完handle_IRQ_event函数之后判断status是否被设置了IRQ_PENDING标志来判断是否还有没有被处理的同一通道的中断请求。 但是这种方法只能判断是否有,而不能知道有多少个未处理的统一通道中断请求。也就是说,假如在第一个中断请求执行handle_IRQ_event函数的过程中来了同一通道的两个或更多中断请求,而这些中断不会再来,那么仅仅通过判断status是否设置了IRQ_PENDING标志不知道到底有多少个未处理的中断,handle_IRQ_event只会被再执行一次。
    这算不算是个bug呢? 不算,只要知道有中断没有处理就OK了,知道1个和知道N个,本质上都是一样的。作为外设,应当能够处理自己中断未被处理的情况。
     
    不可能丢失的,在每一个中断描述符的结构体内,都有一个链表,链表中存放着服务例程序

    关于中断中使用的几个重要概念和关系:

    一、基本概念

    1.

      产生的位置 发生的时刻 时序
    中断 CPU外部 随机 异步
    异常 CPU正在执行的程序 一条指令终止执行后 同步

    2.由中断或异常执行的代码不是一个进程,而是一个内核控制路径,代表中断发生时正在运行的进程的执行

    中断处理程序与正在运行的程序无关

    引起异常处理程序的进程正是异常处理程序运行时的当前进程


    二、特点

    1.(1)尽可能快

    (2)能以嵌套的方式执行,但是同种类型的中断不可以嵌套

    (3)尽可能地限制临界区,因为在临界区中,中断被禁止


    2.大部分异常发生在用户态,缺页异常是唯一发生于内核态能触发的异常

    缺页异常意味着进程切换,因此中断处理程序从不执行可以导致缺页的操作


    3.中断处理程序运行于内核态

    中断发生于用户态时,要把进程的用户空间堆栈切换到进程的系统空间堆栈,刚切换时,内核堆栈是空的

    中断发生于内核态时, 不需要堆栈空间的切换


    三、分类

    1.中断的分类:可屏蔽中断、不可屏蔽中断

    2.异常的分类:

    分类 解决异常的方法 举例
    故障 那条指令会被重新执行 缺页异常处理程序
    陷阱 会从下一条指令开始执行 调试程序
    异常中止 强制受影响的进程终止 发生了一个严重的错误

    四、IRQ

    1.硬件设备控制器通过IRQ线向CPU发出中断,可以通过禁用某条IRQ线来屏蔽中断。

    2.被禁止的中断不会丢失,激活IRQ后,中断还会被发到CPU

    3.激活/禁止IRQ线 != 可屏蔽中断的 全局屏蔽/非屏蔽

    可以有选择地禁止每条IRQ线。因此,可以对PIC编程从而禁止IRQ,也就是说,可以告诉PIC停止对给定的IRQ线发布中断,或者激活它们。禁止的中断时丢失不了的,它们一旦被激活,PIC就又把它们发送到CPU。这个特点被大多数中断处理程序使用,因为这允许中断处理程序逐次地处理同一类型的IRQ

    假定CPU有一条激活的IRQ线。一个硬件设备出现在这条IRQ线程上,且多APIC系统选择我们的CPU处理中断。在CPU应答中断前,这条IRQ线被另一个CPU屏蔽掉;结果,IRQ_DISABLED标志被设置。随后,我们的CPU开始处理挂起的中断;因此,do_IRQ()函数应答这个中断,然后返回,但没有执行中断服务例程,因为它发现IRQ_DISABLED标志被设置了,因此,在IRQ线禁用之前出现的中断丢失了。

    为了应付这种局面,内核用来激活IRQ线的enable_irq()函数先检查是否发生了中断丢失,如果是,该函数就强迫硬件让丢失的中断再产生一次

    它们最大的不同是上半部分不可中断,而下半部分可中断


    五、中断描述符表IDT

    1.基本概念

    中断描述符表是一个系统表,它与每一个中断或异常向量相联系,每一个向量在表中有相应的中断或异常处理程序入口地址。

    在允许发生中断以前,必须适当地初始化IDT

    TSS只能位于GDT中,IDT能位于内存的任何的地方


    2.中断描述符

    硬件提供的中断描述符:

    (1)任务门:中断信号发生时,必须取代当前进程的那个进程的TSS选择符存放在任务门中

    (2)中断门:包含段选择符和中断处理程序的段内偏移

    (3)陷阱门:与中断门的唯一区别是,通过中断门进入服务程序后,自动关中断,而通过陷阱门进入服务程序不自动关中断

    Linux中使用的中断描述符:

    中断描述符的类型 用户态能否访问 用户态的访问方式 能激活的程序
    中断门   所有的Linux中断处理程序
    系统门 into、bound、int $0x80 向量号为4,5,128的三个Linux异常处理程序
    系统中断门 int 3 与向量3相关的异常处理程序
    陷阱门   大部分Linux异常处理程序
    任务门   Linux对Double fault异常的处理程序
    Linux中的系统门、系统中断门、陷阱门使用的都是硬件中的陷阱门

    Linux利用中断门处理中断,利用陷阱门处理异常

    Double fault是唯一用任务处理的异常


    3.中断向量与中断和异常的关系

    (1)每个中断和异常是由0-255之间的一个数来标识的,这个数就是1中的中断向量

    (2)大约有20种异常,内核为每一个异常分配了一种中断/异常向量分别是0-19

    (3)0x80是系统调用的中断向量

    (4)32-255是内核为什么中断分配的中断向量。然而,224个中断向量显然不够,因此系统为每个中断向量设置一个队列,根据每个中断源所使用的中断向量,将其中断服务程序挂到相应的队列中。中断发生时,先执行与中断向量相对应的一段总服务程序,再根据具体的中断源设备号在其所属的队列找到特定的中断服务程序加以执行。


    4.中断向量、与中断向量相对应的总服务程序、某个中断源的中断服务程序之间的关系如图所示:

    (1)irq_desc是中断向量描述符队列(中断描述符是INT的一项,中断向量描述符是一个数据结构,用于描述与中断向量相关的服务程序)

    (2)irq_desc_t是中断向量描述符的数据结构

    (3)irqaction是挂在某个中断向量的具体的中断服务程序的描述符,组成一个队列

    (4)hw_irq_controller是这个中断向量的总服务程序



    六、IDT的初始化

    1.两次初始化

      运行模式 初始值 使用者
    第一次 实模式 空处理程序 BIOS例程
    第二次 保护模式 有意义的中断处理程序或异常处理程序 Linux系统


    2.在IDT表的初始化完成之初,每个中断处理队列都是空的,此时即使打开中断并且某个外设中断真的发生了,也得不到实际的服务,因为没有执行具体的中断处理程序。

    真正的中断服务要到具体设备的初始化程序将其中断处理程序ISR挂入某个中断请求队列后才会发生


    3.在允许发生中断以前,必须适当地初始化IDT


    七、激活中断或异常(以下内容都是由硬件自动完成)

    1.确定与中断或异常相关的中断向量号

    中断:硬件设备控制器通过IRQ向CPU发出信号,中断管制器把接受到的信号转换为中断向量号i

    异常:对于软件指令发出或产生的异常,CPU会差别归类错误的类别,这个类别号就是中断向量

    2.IDT第i项 -----> 段选择符 ----->段描述符 -----> 段基址

    3.IDT第i项 -----> 偏移量

    4.段基址 + 偏移量 -----> 中断处理程序第一条指令的地址

    5.在栈中保存EFLAGS、CS、EIP的内容

    6.如果异常产生了一个出错码,把它保存在栈中

    7.装载CS、EIP,其值分别是2-段选择符和4-偏移量,由这两个寄存器可得到中断或异常处理程序第一条指令的地址



    八、找到中断或异常处理程序的第一条指令后,跳转这到这一指令的过程

    1.中断

    (1)在当前进程的内核堆栈中保存IRQ的值,为什么与系统调用号区分,保存的是-n

    (2)在当前进程的内核堆栈中保存寄存器的值:SAVE_ALL

    EFLAGS、CS、EIP、SS、ESP不包括在内,因为它们由控制单元自动保存(见七-7)

    (3)把栈顶的地址存放到EAX中

    (4)把用户段的选择符装到DS和ES中

    (5)调用do_IRQ(),地址保存在CS、EIP中(见七-7)

    (6)为正在给IRQ线服务的PIC(中断控制器)一个应答,这将允许PIC进一步发出中断

    (7)执行共享这个IRQ的所有设备的ISR(总服务程序称为IRQ,某个设备的具体的服务程序称为ISR

    (8)跳到ret_from_intr()的地址后终止

    (6)(7)(8)都是在(5)中被调用的,见十

    2.异常

    (1)如果异常发生时,控制单元没有自己把一个出错码压出栈中(见七-6),则压入一个空值。

    这个“凑数”的出错码不在正常的出错码应该在的位置,以下-步是为了把它调整到它应该在的位置

    (3)把异常处理程序的地址压入栈中

    (4)把异常处理程度可能用到的寄存器保存到栈中

    (5)把栈中位于ESP+36处的硬件出错码拷贝到EDX中,给栈中这一位置存上-1

    (6)把保存在栈中ESP+32位置的异常处理程序的地址装入EDI中,给栈中的这一位置写入ES的值

    (7)把栈当栈顶拷贝到EAX中

    (8)把用户段的选择符装到DS和ES中

    (9)调用地址在EDI中的异常处理程序


    九、从中断或异常处理程序返回的过程

    1.跳转到用于返回的代码的入口点

    (1)中断ret_from_intr()

    (2)异常:ret_from_exception()

    2.把当前线程描述符的地址装载到EBP

    3.根据栈中的CS和EFLAGS确定要返回到用户态还是内核态

    4.如果有进程调度请求则调度

    5.通过执行iret指令结束控制,被中断的程序重新开始执行


    十、总的中服务务程序IRQ

    1.为正在给IRQ线服务的PIC(中断控制器)一个应答,这将允许PIC进一步发出中断

    2.发生以下任何一种情况,则返回

    (1)相应的IRQ线被禁止

    (2)另一个CPU正常处理这类中断

    (3)没有相关的ISR

    3.执行共享这个IRQ的所有设备的ISR

    4.检查是否有可延迟函数在等待执行,如果有do_softirq()

    5.ret_from_intr()

    十一、中断服务例程
    一个中断服务例程(ISR)实现一种特定设备的操作。当中断处理程序必须执行ISR时,它就调用hand_IRQ_event()函数。

    十二、IRQ线的动态分配
    在激活一个准备利用IRQ线的设备之前,其相应的驱动程序调用request_irq()。这个函数建立一个新的irqaction函数,并用参数值初始化它。然后调用setup_irq()函数把这个描述符插入到适合的IRQ链表。如果setup_irq()返回一个出错码,设备驱动程序中止操作,这意味着IRQ线已有另一个设备所使用,而这个设备不允许中断共享。当设备操作结束时,驱动程序调用free_irq()函数从IRQ链表中删除这个描述符,并释放相应的内存区。
    request_irq()
    free_irq()

    1.Linux把紧随中断要执行的操作分为三类

      特点 处理方法 举例
    第一类 紧急的 在禁止可屏蔽中断的情况下立即执行 修改设备和处理器同时访问的数据结构
    第二类 非紧急的 在开中断的情况下立即执行 修改那些只有处理器才会访问的数据结构(例如,按下一个键后读扫描码)
    第三类 非紧急可延迟的 由独立的函数来执行 把缓冲区的内核拷贝到某个进程的地址空间

    2.把可延迟中断从中断处理程序中抽出来,由独立的函数来执行,有助于使内核保持较短的响应时间


    3.Linux2.6使用可延迟函数和工作队列来处理可延迟中断,这两个都是内核函数。


    二、可延迟函数

    1.可延迟函数包括软中断和tasklet,tasklet是在软中断之上实现的

    tasklet是I/O驱动程序中实现可延迟函数的首选方法。

    tasklet建立在HI_SOFTIRQ和TASKLET_SOFTIRQ这两个软中断之上

    几个tasklet可以与同一软中断相关联,每个tasklet执行自己的函数

      分配方式 并发性 可重入性
    软中断 编译时静态分配 可以并发地在多个CPU上运行 必须是可重入的,并明确地使用自旋锁保护其数据结构
    tasklet 运行时动态分配 相同类型的tasklet总是被串行地执行。不同类型的tasklet可以在几个CPU上并发地执行 不必是可重入的

    2.由给定CPU激活的一个可延迟函数必须在同一个CPU上执行

    可延迟函数执行时不允许内核抢占,因为从一个CPU移到另一个CPU的过程需要将进程挂起


    3.中断与软中断所使用的数据结构比较

      中断 软中断
    中断向量号描述符 irq_desc[中断向量号] softirq_vec[软中断号]
    中断请求寄存器 中断请求寄存器 __softirq_active
    中断屏蔽寄存器 中断屏蔽寄存器 __soft_mask
    中断处理程序 do_handler_name bh[]:32个
    中断处理程序描述项 irqaction softirq_action
    中断机制的初始化 trap_init():异常初始化
    init_IRQ():中断初始化
    softirq_action
    中断请求队列初始化 init_ISA_irqs() open_softirq
    中断处理程序与中断请求队列相关联 request_irq() init_bh()
    执行中断 do_IRQ() do_softirq

    4.激活可延迟函数

    (1)激活软中断

    A.把软中断置为把挂起状态,并周期性地检查处于挂起状态的软中断。如果有,就调用do_softirq()

    B.一般是在以下几个点来检查挂起的软中断的a.调用local_bh_enable()激活本地软中断时b.do_IRQ()完成I/O中断的处理即将退出时c.用于周期性检查挂起状态软中断的内核线程ksoftirqd被唤醒时d.else,我觉得不太重要

    (2)激活tasklet

    A.把自己定义的描述符加入到tasklet_vec指向的链表中即可。调用tasklet_action()时,依次处理队列中的每个tasklet描述符,然后清空tasklet_vec指向的链表。

    B.tasklet的每次激活至多触发tasklet函数的一次执行,除非tasklet函数重新激活自己


    三、工作队列

    1.它们允许内核函数被激活,并稍后由一种叫做工作者线程的特殊内核线程来执行

    如果系统有n个CPU,就会创建n个工作者,但是只会创建一个工作队列


    2.工作队列与可延迟函数的区别:

    可延迟函数运行中断上下文中,而工作队列运行在进程中下文中。

    可延迟函数不能阻塞,工作队列可执行可阻塞函数

    可延迟函数被执行时不可能有任何正在运行的进程,工作队列中的函数由内核线程来执行,不访问用户态地址空间


    3.工作队列的激活

    把要执行的函数的描述符插入到工作队列中。

    工作者等待函数被插入队列,被唤醒后把函数描述符取下并执行。

    由于工作队列函数可以阻塞,工作者线程可以睡觉,或移动另一个CPU


    总而言之:

           当发生一个中断时,如果发现中断被屏蔽,这个中断好似不会丢失的,会被再次触发!!

    展开全文
  • linux中断嵌套以及中断丢失

    千次阅读 2014-05-07 23:01:20
    在linux内核里,如果驱动在申请注册中断的时候没有特别的指定,do_irq在做中断响应的时候,是开启中断的,如果在驱动的中断处理函数正在执行过程中,出现同一设备的中断或者不同设备的中断,这时候新的中断会被...

    在linux内核里,如果驱动在申请注册中断的时候没有特别的指定,do_irq在做中断响应的时候,是开启中断的,如果在驱动的中断处理函数正在执行的过程中,出现同一设备的中断或者不同设备的中断,这时候新的中断会被立即处理,还是被pending,等当前中断处理完成后,再做处理。
    在2.4和2.6内核里,关于这一块是否有什么不同。

    一般申请中断的时候都允许开中断,即不使用SA_INTERRUPT标志。如果允许共享则加上 SA_SHIRQ,如果可以为内核熵池提供熵值(譬如你写的驱动是ide之类的驱动),则再加上 SA_SAMPLE_RANDOM标志。这是普通的中断请求过程。对于这种一般情况,只要发生中断,就可以抢占内核,即使内核正在执行其他中断函数。这里有两点说明:一是因为linux不支持 中断优先级,因此任何中断都可以抢占其他中断,但是同种类型的中断(即定义使用同一个 中断线的中断)不会发生抢占,他们会在执行本类型中断的时候依次被调用执行。二是所谓 “只要发生中断,就可以抢占内核”这句是有一定限制的,因为当中断发生的时候系统由中断门 进入时自动关中断(对于x86平台就是将eflags寄存器的if位置为0),只有当中断函数被执行 (handle_IRQ_event)的过程中开中断之后才能有抢占。 对于同种类型的中断,由于其使用同样的idt表项,通过其状态标志(IRQ_PENDING和 IRQ_INPROGRESS)可以防止同种类型的中断函数执行(注意:是防止handle_IRQ_event被重入, 而不是防止do_IRQ函数被重入),对于不同的中断,则可以自由的嵌套。因此,所谓中断嵌套, 对于不同的中断是可以自由嵌套的,而对于同种类型的中断,是不可以嵌套执行的。
    以下简单解释一下如何利用状态标志来防止同种类型中断的重入:
    当某种类型的中断第一次发生时,首先其idt表项的状态位上被赋予IRQ_PENDING标志,表示有待处理。 然后将中断处理函数action置为null,然后由于其状态没有IRQ_INPROGRESS标志(第一次),故将其状态置上IRQ_INPROGRESS并去处IRQ_PENDING标志,同时将action赋予相应的中断处理函数指针(这里是一个重点,linux很巧妙的用法,随后说明)。这样,后面就可以顺利执行handle_IRQ_event进行中断处理,当在handle_IRQ_event中开中断后(我认为应该是回复EOI给PCI),如果有同种类型的中断发生,则再次进入do_IRQ函数,然后其状态位上加上IRQ_PENDING标志,但是由于前一次中断处理中加上的IRQ_INPROGRESS没有被清除,因此这里无法清除IRQ_PENDING标志,因此action还是为null,这样就无法再次执行handle_IRQ_event函数。从而退出本次中断处理,返回上一次的中断处理函数中,即继续执行handle_IRQ_event函数。当handle_IRQ_event返回时检查IRQ_PENDING标志,发现存在这个标志,说明handle_IRQ_event执行过程中被中断过,存在未处理的同类中断,因此再次循环执行handle_IRQ_event函数。直到不存在IRQ_PENDING标志为止。

    2.4和2.6的差别,就我来看,主要是在2.6中一进入do_IRQ,多了一个关闭内核抢占的动作,同时在处理中多了一种对IRQ_PER_CPU类型的中断的处理,其他没有什么太大的改变。这类IRQ_PER_CPU的中断主要用在smp环境下将中断绑定在某一个指定的cpu上。例如arch/ppc/syslib/open_pic.c中的openpic_init中初始化ipi中断的时候。

    关于do_IRQ可能会丢失中断请求。
    do_IRQ函数是通过在执行完handle_IRQ_event函数之后判断status是否被设置了IRQ_PENDING标志来判断是否还有没有被处理的同一通道的中断请求。 但是这种方法只能判断是否有,而不能知道有多少个未处理的统一通道中断请求。也就是说,假如在第一个中断请求执行handle_IRQ_event函数的过程中来了同一通道的两个或更多中断请求,而这些中断不会再来,那么仅仅通过判断status是否设置了IRQ_PENDING标志不知道到底有多少个未处理的中断,handle_IRQ_event只会被再执行一次。
    这算不算是个bug呢? 不算,只要知道有中断没有处理就OK了,知道1个和知道N个,本质上都是一样的。作为外设,应当能够处理自己中断未被处理的情况。


    展开全文
  • 现在我们来分析,在可能出现中断嵌套的情况下,10ms定时中断如何完成线程切换。 有一个链表,链表头是旧线程,链表尾是新线程,链表中间有多个独立中断、多个嵌套中断,被嵌套中断会在这个链表中的多个位置出现,...
  • 而关键是在处理过程中调用的函数层级比较深以至于不记得现在是在中断程序里执行(还是在Debug的Call Back中发现是中断调用的),有一个错误情况被我处理为关闭模块电源等待一段时间再复位芯片工作,...
  • 引起CPU暂时中断正在运行的程序,转去执行一段特殊的服务程序(中断服务子程序或中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序继续执行,这一过程称为中断。 比如打游戏时来电话了。 嵌套向量中断...
  • 中断:(英语:Interrupt)指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新...
  • 中断和异常的定义中断(interrupt)指在程序执行过程中遇到急需处理的事件时,暂时中止现行程序在 CPU 上的运行,转而执行响应的事件处理程序,待处理完成后再返回断点或调度其他程序。cpu对事件的响应.中断的本质是...
  • 中断: (英语:Interrupt)指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这...
  • Linux中断简介和单片机中断类似,Linux中断是指CPU在运行程序过程中,由于内部或者外部的事件引起的使得CPU暂停正在运行的程序,去执行该内部事件或外部事件的引起的服务中去,服务执行完毕后再返回断点处继续执行的...
  • 这个部分的内容是写在HAL库的GPIO外部中断 EXTI15_10_IRQHandler10中的回调函数HAL_GPIO_EXTI_Callback中,HAL库的逻辑是执行完回调函数然后配置好了关闭中断的函数,所以一般不需要在回调函数里用完之后手动关闭。...
  • 切换是嵌套中断上下?切换中的,?如系统调?作为?种中断先陷?内核,即发?中断保存现场和系统调?处理过程。其中调?了schedule函数发?进程上下?切换,当系统调?返回到?户态时会恢复现场,?此完成了保...
  • PIE/CPU中断响应过程

    2021-01-06 13:17:28
    I、CPU响应,进入中断服务子程序前,DSP硬件自动将IFRx清0,然后将CPU内一些关键寄存器如:ST0、ST1及IER等的内容压到堆栈保存起来,随后硬件自动将IERx清0,INTM置1,以避免中断嵌套,在中断服务子程序执行完返回后...
  • 文章目录第八章 中断系统8.1 中断的基本概念8.1.1 中断概念的引入及描述中断方式示意(以输入中断为例)**中断**的定义...中断嵌套4.中断系统应具备的基本功能8.3 80x86的中断指令INT n指令的执行过程8.4 中断控制器8
  • 2、单片机在执行定时器中断时,是否在没执行当前中断情况再次执行定时器中断(中断嵌套?) 解决:中断在执行时,如果又有一个中断产生,将不会进入中断函数,知道当前中断执行结束后,才允许下一个新的中断进入。 ...
  • 多重中断的处理及其中断源屏蔽字

    千次阅读 2021-01-08 19:25:09
    如果CPU在执行某一中断服务程序过程中,又遇到了新的更高级的中断请求,CPU暂停原中断的处理,而转去处理新的中断,待处理完毕后,再返回继续处理原来的中断,这种中断称为多重中断,也称中断嵌套。 2、多重中断的...
  • 1、在linux中,对中断的处理有原则 对中断的处理原则有两个: 1)、中断不能嵌套中断(即使发生了更高...为了避免这个问题,不允许中断嵌套。 2)、对中断的处理应当越快越好。 假设系统只有一个CPU,一个进程在执
  • 单片机之中断

    千次阅读 2021-01-07 19:26:31
    中断的概念 日常生活的中断现象举例 中断是指在突发事件到来时先中止当前正在进行的工作...中断嵌套:在中断服务过程执行 更高级别的中断服务。 中断过程与调用一般函数过程的相似性: 两者都需要保护断点...
  • 中断执行流程: 主程序执行过程可以产生中断去执行中断的内容(保护现场),然后在返回继续执行中断.中断分类:(可以在参考手册查看)系统异常:内核水平 10个外部中断:外设水平 60个有关具体的系统异常和外部中断可在标准...
  • 【UCOSIII】UCOSIII的中断和时间管理

    万次阅读 2018-06-28 19:36:03
    UCOSIII的中断管理 UCOSIII中断处理过程 在STM32中是支持中断的,中断是一个硬件机制,主要用来向CPU通知一个异步事件发生了,这时CPU就会将当前CPU寄存器值...UCOSIII是支持中断嵌套的,即高优先级的中断可以打断...
  • 微型计算机的中断系统中断原理中断的基本概念中断中断源中断识别中断断点中断服务程序中断系统中断管理中断源的识别中断的优先级中断嵌套中断过程中断源请求中断中断响应中断响应周期8086 CPU中断系统中断类型外部...
  • 中断分层和按键去抖

    2017-08-15 09:07:04
    有另一个优先级更高的中断提出中断请求,这时会暂时终止当前正在执行的级别较低的中断源的服务程序,去处理级别更高的中断源,待处理完毕,再返回到被中断了的中断服务程序继续执行,这个过程就是中断嵌套。...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 166
精华内容 66
关键字:

中断嵌套执行过程