近水楼台

Linux中断处理

 

基于内核2.4.0,硬件i386

基本处理

下图为硬件在接收到中断的时候(未被屏蔽),响应中断请求,寻找中断服务程序的过程。


基于这样的硬件服务,操作系统要做的就是:

        编制中断处理程序或者提供用户登记其中断服务程序的机制

        初始化中断向量表IDT
                 void __init trap_init(void)
                 void __init init_IRQ(void)

        加载IDT
                 ldtr

外部中断的处理与中断请求队列

I386系统结构支持256个中断向量,扣除一些为CPU本身保留的向量,剩下的可能不够用。

那么很多外部设备就不得不共用中断向量

Linux的处理方法就是:

系统为每个中断向量设置一个队列

设置数组irq_desc[],其中每个元素为这样一个队列 的头部以及控制结构。

当中断发生时,首先执行与中断向量相对应的一段总服务程序,

根据中断源的设备号在其所属队列中找其对应的服务程序加以执行。

下图为其中数据结构的指向流图,也表明了些函数调用的过程。



中断处理过程:

外部中断处理函数的入口
        IRQ0xY_interrupt:

总服务程序
        common_interrupt:

执行跟中断向量相关的控制,调用中断处理函数
        do_IRQ(struct pt_regs regs)

处理中断
        handle_IRQ_envent(unsigned irq, struct pt_regs *regs, struct irqaction *action)

其中中断请求队列的初始化:

数组
        extern irq_desc_t irq_desc[NR_IRQ]

数组初始化
        void __init init_ISA_irqs(void)

设备向系统登记其中断服务程序
        int request_irq(unsigned int irq,
                void (*handler)(int, void*, struct pt_regs),
                unsigned long irqflags,
                const char * devname,
                void *dev_id)

将action链入相应的中断请求队列
        setup_irq(unsigned int irq, struct irqactiong *new)

软中断与bottom half

中断服务一般都是在关中断条件下执行,但是入关关中断时间太长可能因为CPU不能及时响应其他中断而使中断请求丢失。

操作系统都把中断分成了两个部份,上半部份与下半部份。上半部份通常是响应中断,并把中断所得到的数据保存进下半部。

耗时的操作一般都会留到下半部去处理。后半部分即bottom half,简称bh。

软中断通常是硬中断服务程序对内核的中断。它利用硬件中断的概念,用软件方式进行模拟,实现宏观上的异步执行效果。

Linux用软中断机制实现bh。

一些数据结构:

关于软中断

        向量表
            static struct softirq_action soft_vec[32]

        软中断请求寄存器(某个软中断向量上有了请求,相应位置1)
            __soft_active

        软中断屏蔽寄存器
            __soft_mask

基于tasklet
        struct tasklet_struct bh_task_vec[32]

bh函数数组
        bh_base[32]

下以时钟中断为例说明用软中断实现bh的过程。

下图详述了各个数据结构初始化的过程以及bh实现的函数调用过程。

 

说明

bh实现的函数调用过程:

响应软中断
        在do_IRQ()执行完一个通道中的中断服务程序后以及在每当从系统    调用返回时,调用do_softirq()

进入do_softirq()
        通过softirq_active和softirq_mask的标志位确定哪个软中断向量提出了软中断请求需要处理,

        调用软中断处理函数soft_vec[i]->action(h)

软中断处理函数tasklet_hi_action()
        访问当前cpu的tasklet_hi_vec[cpu],根据此链表访问bh_task_vec[i],

         调用bh_task_vec[i]->action(data)

执行bh_action()
        访问bh_base[]数组,依次执行存在的bh函数

执行bh_action()

各个数据结构的初始化

软中断向量表soft_vec[]
        softirq_init()->open_softirq()

bh_task_vec[]初始化
        softirq_init()->tasklet_init()

bh_task_vec[]链接到tasklet_hi_vec[cpu]
        mark_bh()->task_hi_schedule()

bh_base[]置值
        init_bh()

 

以上为看了Linux内核情景分析中断异常这一章做的一个小结。仅述了一个基本的逻辑过程,细节方面没作详述。


 

Just the Beginning

啦啦啦!啦啦啦!我是卖报的小行家
不等天明去等派报
一面走,一面叫
今天的新闻真正好
七个铜板就买两份报。
啦啦啦!啦啦啦!我是卖报的小行家
大风大雨里满街跑
走不好,滑一跤
满身的泥水惹人笑
饥饿寒冷只有我知道
啦啦啦!啦啦啦!我是卖报的小行家
耐饥耐寒地满街跑
吃不好,睡不好
痛苦的生活向谁告
总有一天光明会来到

开篇权当娱乐吧!!

 

 




Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee