简介
当调用request_irq、request_threaded_irq注册中断处理函数时,内核就会构造一个irqaction结构体。在里面保存name、dev_id等,最重要的是handler、thread_fn、thread。
struct irqaction {
irq_handler_t handler;
void *dev_id;
void __percpu *percpu_dev_id;
struct irqaction *next;
irq_handler_t thread_fn;
struct task_struct *thread;
struct irqaction *secondary;
unsigned int irq;
unsigned int flags;
unsigned long thread_flags;
unsigned long thread_mask;
const char *name;
struct proc_dir_entry *dir;
} ____cacheline_internodealigned_in_smp;
handler是中断处理的上半部函数,用来处理紧急的事情。
thread_fn对应一个内核线程thread,当handler执行完毕,Linux内核会唤醒对应的内核线程。在内核线程里,会调用thread_fn函数。
可以提供handler而不提供thread_fn,就退化为一般的request_irq函数。
也可以既提供handler也提供thread_fn,这就是中断上半部、下半部。
在reqeust_irq时可以传入dev_id,为何需要dev_id?作用有以下两个作用:
- 中断处理函数执行时,可以使用dev_id
- 卸载中断时要传入dev_id,这样才能在action链表中根据dev_id找到对应项
所以在共享中断中必须提供dev_id,非共享中断可以不提供。
可以参考
共享中断做起来比较浪费时间。简单的可以从单片机只有一个中断入口理解,产生中断后,在这个入口里面判断标志位,查看是什么中断产生的。不过这是很低端的单片机了。那么共享中断就是表示,多个外设的中断只有一个中断入口。当这个中断入口被调用的时候。遍历对应链表里面的中断函数。在这个函数里面来判断是否产生了中断。
换句话说,假设有A,B,C,D四个外设共享一个10号中断。那么当D中断产生了以后,10号中断的入口函数被调用。然后遍历A,B,C,D的中
断服务函数。每个中断函数都会被执行。但是A,B,C的中断函数一执行,判断不是此中断产生,就会返回。直到D的中断处理被调用。
共享中断如此麻烦,现在的硬件一般都不会采用共享中断的模式了。
request_irq 函数会注册一个irqaction结构。 然后最重要的操作是填充 handler。这个就是最常用的中断处理函数。
thread_fn这个参数就需要提到中断线程化了。这个参数就是新增的request_threaded_irq 函数 函数填充的变量。
__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
{
if (new->thread_fn && !nested) {
ret = setup_irq_thread(new, irq, false);
...
}
setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary)
{
struct task_struct *t;
if (!secondary) {
t = kthread_create(irq_thread, new, "irq/%d-%s", irq, new->name);
...
}
中断线程化
参考Linux中的中断处理机制 [六] 文章。
中断处理方式
我们知道中断的上下文一般有以下四种形式。
每一个内核维持了一个 worker_pool 。 属于绑定队列(bound queues)。一个worker_pool 里面可能包含了一个或者多个worker。这个worker可以简单的理解为
一个执行工作的线程。当满足要求以后,这个worker就会执行特定的work.
**
Threaded IRQs
参考文档
线程中断化使用的是 request_threaded_irq 函数。注册了一个irqaction结构体。填充了thread_fn以及handler。
request_threaded_irq()的主要作用就是填写”irq_action”结构体,包括第二级的处理函数”handler”和”thread_fn”,区分共享IRQ的不同设备的”dev_id”和”devname”等。
Softirq
Tasklets
历史
参考资料
韦东山:剥丝抽茧分析Linux中断系统中的重要数据结构
Linux 设备驱动 Edition 3
源码解读Linux等待队列 - Gityuan博客 | 袁辉辉的技术博客
3-工作队列使用-Workqueue
Linux的中断处理机制 [三] - hardirq
Linux中的中断处理机制 [六]
**