Chinaunix首页 | 论坛 | 博客
  • 博客访问: 301648
  • 博文数量: 43
  • 博客积分: 3000
  • 博客等级: 中校
  • 技术积分: 790
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-06 15:15
文章分类

全部博文(43)

文章存档

2011年(11)

2010年(14)

2009年(7)

2008年(11)

我的朋友

分类: LINUX

2010-06-09 15:35:39

linux中断处理体系结构

linux内核将所有的中断统一编号,使用一个irq_desc结构数组来描述这些中断。通过irq_desc结构数组就可以了解中断处理体系结构,irq_desc结构的数据类型在include/linux/irq.h中定义,如下所示:

struct irq_desc {

       irq_flow_handler_t handle_irq; //当前中断的处理函数入口

       struct irq_chip              *chip; //低层的硬件访问

       struct msi_desc             *msi_desc;

       void               *handler_data;

       void               *chip_data;

       struct irqaction       *action;   /* IRQ action list 用户提供的中断处理函数链表*/

       unsigned int           status;            /* IRQ status */

       unsigned int           depth;            /* nested irq disables */

       unsigned int           wake_depth;   /* nested wake enables */

       unsigned int           irq_count;       /* For detecting broken IRQs */

       unsigned int           irqs_unhandled;

       unsigned long         last_unhandled;      /* Aging timer for unhandled count */

       spinlock_t              lock;

#ifdef CONFIG_SMP

       cpumask_t             affinity;

       unsigned int           cpu;

#endif

#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)

       cpumask_t             pending_mask;

#endif

#ifdef CONFIG_PROC_FS

       struct proc_dir_entry     *dir;

#endif

       const char             *name; //中断名称

} ____cacheline_internodealigned_in_smp;

上面结构数组中的handle_irq是这个或这组中断的处理函数入口,发生中断时,总入口函数asm_do_IRQ将根据中断号调用相应irq_desc数组项中的handle_irqhandle_irq使用chip结构中的函数来清除,屏蔽后者重新使能中断,还一一调用用户在action链表中注册的中断处理函数。

irq_chip结构类型也是在include/linux/irq.h中定义,其中的成员大多数用于操作底层硬件,比如设置寄存器以屏蔽中断,使能中断,清除中断等等。这个结构的成员如下:

struct irq_chip {

       const char      *name;

       unsigned int    (*startup)(unsigned int irq);//启动中断,如果不设置,缺省为“enable

       void        (*shutdown)(unsigned int irq);//关闭中断,如果不设置,缺省为“disable

       void        (*enable)(unsigned int irq);//使能中断,如果不设置,缺省为”unmask”

       void        (*disable)(unsigned int irq);//禁止中断,如果不设置,缺省为“mask

       void        (*ack)(unsigned int irq);//响应中断,通常是清除当前中断使得可以接受下一个中断

       void        (*mask)(unsigned int irq);//屏蔽中断源

       void        (*mask_ack)(unsigned int irq);//屏蔽和相应中断源

       void        (*unmask)(unsigned int irq);//开启中断源

       void        (*eoi)(unsigned int irq);

       void        (*end)(unsigned int irq);

       void        (*set_affinity)(unsigned int irq, cpumask_t dest);

       int           (*retrigger)(unsigned int irq);

       int           (*set_type)(unsigned int irq, unsigned int flow_type);

       int           (*set_wake)(unsigned int irq, unsigned int on);

       /* Currently used only by UML, might disappear one day.*/

#ifdef CONFIG_IRQ_RELEASE_METHOD

       void        (*release)(unsigned int irq, void *dev_id);

#endif

       /*

       * For compatibility, ->typename is copied into ->name.

       * Will disappear.

       */

       const char      *typename;

};

上面结构数组irq_desc中的irqaction结构类型在include/linux/interrupt.h中定义。用户注册的每个中断处理函数用一个irqaction结构来表示,一个中断可以有多个处理函数,他们的irqaction结构连接成一个链表,以action为表头。irqaction结构定义如下:

struct irqaction {

       irq_handler_t handler;//用户注册的中断处理函数

       unsigned long flags;//中断标志,比如是否共享中断标志,电平触发还是边沿触发

       cpumask_t mask;//用于SMP(对称多处理系统)

       const char *name;//用户注册的中断名字,在/proc/interrupts中可以看到

       void *dev_id; //用户传给上面的handler的参数,还可以用来区分共享中断

       struct irqaction *next;

       int irq;//中断号

       struct proc_dir_entry *dir;

};

综上,中断处理流程如下:

1.发生中断时,CPU执行异常向量vector_irq的代码。

2.vector_irq里面,最终会调用中断处理的总入口函数asm_do_IRQ

3,asm_do_IRQ根据中断号调用irq_desc数组项中的handle_irq

4handle_irq会使用chip成员中的函数来设置硬件,比如清除中断,禁止中断,重新使能中断等。

5.handle_irq逐个调用用户在action链表中注册的处理函数。

可见,中断体系结构的初始化就是构造这些数据结构,比如irq_desc数组项中的handle_irq,chip等成员,用户注册中断时就是构造action链表,用户卸载中断时就是从action链表中去除不需要的项。
阅读(1123) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~