在linux里,中断处理分为顶半(top half),底半(bottom half),在顶半里处理优先级比较高的事情,要求占用中断时间尽量的短,在处理完成后,就激活底半,有底半处理其余任务。底半的处理方式主要有soft_irq, tasklet, workqueue三种,他们在使用方式和适用情况上各有不同。soft_irq用在对底半执行时间要求比较紧急或者非常重要的场合,主要为一些subsystem用,一般driver基本上用不上。 tasklet和work queue在普通的driver里用的相对较多,主要区别是tasklet是在中断上下文执行,而work queue是在process上下文,因此可以执行可能sleep的操作。
request_threaded_irq()是Linux kernel 2.6.30 之后新加的irq handler API
如何确定可以用到 request_threaded_irq() ?
Linux kernel config 需要定义CONFIG_GENERIC_HARDIQS
kernel config 才有支援threaded irq
Moving interrupts to threads 介绍request_threaded_irq() 的由来
http://lwn.net/Articles/302043/
从realtime tree 移植而来,为了减少kernel 因为要等待每一个硬件中断处理的时间
,就另外交给kernel thread 处理中断后续工作。
优点:
1 减少 kernel 延迟时间
2 避免处理中断时要分辨是在硬体中断或软体中断?
3 更容易为kernel 中断处理除错,可能可完全取代tasklet
原本的中断处理分上半部(硬体中断处理,必须关闭中断无法处理新的中断)跟下半部(
软体中断处理),因此上半部的硬体中断处理必须尽可能简短,让系统反应速度更快。
request_threaded_irq 是在将上半部的硬件中断处理缩短为只确定硬体中断来
自我们要处理的装置,唤醒kernel thread 执行后续中断任务。
缺点:
对于非irq 中断的kernel threads ,需要在原本task_struct 新增struct
irqaction 多占 4/8 bytes 记忆体空间
linux kernel 2.6.29 之后(2.6.30)加入request_threaded_irq
跟传统top/bottom havles 的差异是threaded_irq 受Linux kernel system
的 process scheduling 控制,不会因为写错的bottom half 代码造成整个系统
延迟的问题。
也可以透过RT/non RT 跟nice 等工具调整各个thread 优先权,丢给使用率较低的
cpu 以及受惠于kernel 原本可以对threads 做的各种控制,包括但不限于sleep,
lock, allocate 新的记忆体区块。
受惠最大的是shared irq line 的多个中断处理。除了可以加速共享中断造成的延迟
,threaded_irq 也可以降低在同一段程式码处理多个装置中断的复杂度。
threaded irq 在使用性上也比tasklet(接着top half 直接执行,无法sleep)
/workqueue(kernel context?) 等需要在top half 增加跟bottom half 连结与沟通
的麻烦。
int request_threaded_irq(unsigned int
申请中断request_irq()与request_threaded_irq()之间的不同?
