简介
本片文章的目的主要是为了深入理解request_irq函数。来分析Linux怎么处理中断函数的。
static inline int __must_check
request_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;
# 设置irq
retval = __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 | grep
arch/arm/include/asm/irq.h
arch/arm/mach-davinci/include/mach/irqs.h
arch/arm/mach-ebsa110/include/mach/irqs.h
include/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 调用约定