Linux内核-中断-中断响应和返回

一、中断的响应和服务

在前面一篇博文中,我们分析了i386 CPU的中断机制和内核中有关的初始化,现在我们进一步分析中断的响应过程和服务(和异常的响应机制不同)。我们假设外设驱动都已经完成了初始化,并且已把相应的中断服务程序挂入到特定的中断请求队列中,系统正在用户空间正常运行,并且某个外设已经产生了一次中断请求,该请求通过中断控制器到达了CPU的“中断请求”引线INTR。CPU从中断控制器取得中断向量,然后根据具体的中断向量从中断向量表IDT中找到相应的表项,该表项为一个中断门,然后通过该中断门的设置到达了该通道的总服务程序的入口IRQxx_interrupt,即为interrupt[]中的元素(参考前面一篇文章),这里为了方便说明,再次给出IRQxx_interrupt等的源码,如下:

 pushl $vector-256
    jmp common_interrupt

    /* common_interrupt如下 */
    common_interrupt:
    SAVE_ALL
    movl %esp,%eax
    call do_IRQ
    jmp ret_from_intr


    /* SAVE_ALL如下 */
    #define SAVE_ALL \
    cld; \
    pushl %es; \
    pushl %ds; \
    pushl %eax; \
    pushl %ebp; \
    pushl %edi; \
    pushl %esi; \
    pushl %edx; \
    pushl %ecx; \
    pushl %ebx; \
    movl $(__USER_DS), %edx; \
    movl %edx, %ds; \
    movl %edx, %es;

在SAVE_ALL后,堆栈如图:

这里写图片描述

接下来将栈顶指针esp存到eax中,然后执行do_IRQ函数,该函数声明如下:

 fastcall unsigned int do_IRQ(struct pt_regs *regs)

    /* 关键字regparm表示函数到eax寄存器中去找到参数regs的值 */
    #define fastcall    __attribute__((regparm(3)))

    /* 到此可以清楚的看到,regs指向的内容为上图中系统堆栈中的内容 */
    struct pt_regs {
        long ebx;
        long ecx;
        long edx;
        long esi;
        long edi;
        long ebp;
        long eax;
        int  xds;
        int  xes;
        long orig_eax;
        long eip;
        int  xcs;
        long eflags;
        long esp;
        int  xss;
    };

接下来分析do_IRQ()函数,如下:

 /** 
     * do_IRQ执行与一个中断相关的所有中断服务例程.
     */
    fastcall unsigned int do_IRQ(struct pt_regs *regs)
    {   
        /* 通过orig_eax读回并屏蔽掉高位,又得到中断号irq */
        int irq = regs->orig_eax & 0xff;
    #ifdef CONFIG_4KSTACKS
        union irq_ctx *curctx, *irqctx;
        u32 *isp;
    #endif

        /**
         * irq_enter增加中断嵌套计数
         */
        irq_enter();

    #ifdef CONFIG_DEBUG_STACKOVERFLOW
        /* Debugging check for stack overflow: is there less than 1KB free? */
        {
            long esp;

            __asm__ __volatile__("andl %%esp,%0" :
                        "=r" (esp) : "0" (THREAD_SIZE - 1));
            if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) {
                printk("do_IRQ: stack overflow: %ld\n",
                    esp - sizeof(struct thread_info));
                dump_stack();
            }
        }
    #endif

    #if
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值