1. Linux异常处理体系结构
Linux异常处理体系结构使用主要分成两步:
1、使用函数init_IRQ()初始化中断体系结构,源代码在arch/arm/kernel/irq.c中。
2、用户使用函数request_irq()向内核注册中断处理函数,也就是通过中断号找到irq_desc数组项,将中断函数添加到action链表中。
作者分析的内核版本为2.6.22.6。
1.1 Linux中断处理体系结构初始化
Linux内核将所有中断统一编号,使用一个irq_desc结构数组描述,每个数组项对应一个中断,irq结构数据类型在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; /* 用户提供的中断处理函数链表 */
unsigned int status; /* IRQ 状态 */
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;
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.c文件中(在/kernel/irq中定义),定义了irq_desc结构数组,如下:
struct irq_desc irq_desc[NR_IRQS]
#define NR_IRQS 128
irq_desc结构数组中成员hanle_irq结构,它包括操作底层硬件的函数,如清除、屏蔽或者重新使能中断,其类型在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); /* 禁止中断,如果不设置,缺省为disable */
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,