简介
本片文章的目的主要是为了深入理解request_irq函数。来分析Linux怎么处理中断函数的。
static inline int __must_checkrequest_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)request_threaded_irq(irq, handler, NULL, flags, name, dev); # 我们使用 request_irq ,显然不属于线程中断。因此 thread_fn 设置为 thread_fn , 很多时候我们只需要关注 irq 和 handler 就可以了int request_threaded_irq(unsigned int irq, irq_handler_t handler, # irq 软中断号 中断的回调函数irq_handler_t thread_fn, unsigned long irqflags,const char *devname, void *dev_id)desc = irq_to_desc(irq); # 从 irq_desc 数组返回描述符action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); # 分配 irqaction 结构体action->handler = handler; # 中断的回调函数action->thread_fn = thread_fn; # 线程化的函数action->flags = irqflags;action->name = devname;action->dev_id = dev_id;# 设置irqretval = __setup_irq(irq, desc, action);#
irq_to_desc
这个函数将会通过 irq 来访问 irq_desc 数组。
struct irq_desc *irq_to_desc(unsigned int irq){return (irq < NR_IRQS) ? irq_desc + irq : NULL;}
irq_desc 数组是怎么定义的了?
struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {[0 ... NR_IRQS-1] = {.handle_irq = handle_bad_irq,.depth = 1,.lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),}};
按照上面的代码,我们可以知道这个数组长度为NR_IRQS
root@zhou 23:14:53 ~/1/1/Linux-4.9.88 # global NR_IRQS | greparch/arm/include/asm/irq.harch/arm/mach-davinci/include/mach/irqs.harch/arm/mach-ebsa110/include/mach/irqs.hinclude/asm-generic/irq.h
我并没有在对应的mach文件夹下面找到NR_IRQS ,因此可以推测,是在 include/asm-generic/irq.h 中。
# include/asm-generic/irq.h#define NR_IRQS 64
__setup_irq
这个函数将会注册一个irqaction 结构体。然后链接到irq_desc结构体中。
static int __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)old_ptr = &desc->action; # 保存当前的 desc 地址,old = *old_ptr; # 取old_ptr 指向的地址的数据 地址# 这里很重要,将传进来的 new 链接到 desc 的成员参数do {/** Or all existing action->thread_mask bits,* so we can find the next zero bit for this* new action.*/thread_mask |= old->thread_mask;old_ptr = &old->next; # 获得下一个 irqaction的二级指针old = *old_ptr; # 得到其地址} while (old); # 找到一个为NULL 的 irqaction*old_ptr = new; # 将新的 irqaction 放进来
参考资料
ARM 软中断指令SWI
Linux系统调用列表
韦东山:剥丝抽茧分析Linux中断系统中的重要数据结构
21.7。Linux系统调用
21.8.2. ARM 调用约定
