2. 中断处理流程
2.1 中断注册与注销
在 Linux 内核中,设备驱动程序通过 request_irq() 和 free_irq() 函数完成中断处理函数的注册与注销。这两个函数是中断子系统提供给驱动层的标准接口。
2.1.1 中断注册函数
int request_irq(unsigned int irq,
irq_handler_t handler,
unsigned long flags,
const char *name,
void *dev);
| 参数 | 说明 |
|---|---|
irq |
中断号,由硬件平台决定或通过 platform_get_irq() 获取 |
handler |
中断处理函数指针,类型为 irq_handler_t |
flags |
中断标志位,控制中断触发方式、共享属性等 |
name |
设备名称,在 /proc/interrupts 中显示 |
dev |
传递给中断处理函数的设备标识,共享中断时用于区分设备 |
2.1.2 中断注销函数
void free_irq(unsigned int irq, void *dev);
最佳实践:中断注册应在设备初始化成功、硬件准备就绪后调用;中断注销应在设备移除或驱动卸载时调用,且必须在释放可能触发中断的硬件资源之前完成。
2.2 中断处理函数原型
Linux 内核定义的中断处理函数原型如下:
typedef irqreturn_t (*irq_handler_t)(int irq, void *dev_id);
返回值类型 irqreturn_t 为枚举:
| 返回值 | 宏定义 | 含义 |
|---|---|---|
IRQ_NONE |
#define IRQ_NONE (0) |
中断不是本设备产生的,继续传递给下一个共享处理函数 |
IRQ_HANDLED |
#define IRQ_HANDLED (1) |
中断已被本设备处理,中断处理结束 |
IRQ_WAKE_THREAD |
#define IRQ_WAKE_THREAD (2) |
唤醒中断线程化处理函数( threaded IRQ ) |
关键约束:中断处理函数运行在中断上下文中,必须遵循以下规则:
• 不能调用可能导致睡眠的函数(如
• 不能访问用户空间内存
• 执行时间应尽可能短,通常只做最紧急的硬件操作
• 耗时任务应推迟到下半部( bottom half )处理
• 不能调用可能导致睡眠的函数(如
kmalloc(GFP_KERNEL)、mutex_lock()、copy_from_user())• 不能访问用户空间内存
• 执行时间应尽可能短,通常只做最紧急的硬件操作
• 耗时任务应推迟到下半部( bottom half )处理
2.3 中断标志位详解
flags 参数通过位掩码组合控制中断行为,常用标志如下:
| 标志位 | 值 | 说明 |
|---|---|---|
IRQF_SHARED |
0x00000001 | 允许多个设备共享同一中断线,必须配合 dev_id 参数使用 |
IRQF_TRIGGER_RISING |
0x00000002 | 上升沿触发 |
IRQF_TRIGGER_FALLING |
0x00000004 | 下降沿触发 |
IRQF_TRIGGER_HIGH |
0x00000008 | 高电平触发 |
IRQF_TRIGGER_LOW |
0x00000010 | 低电平触发 |
IRQF_ONESHOT |
0x00000020 | 中断处理期间硬件中断线被屏蔽,处理完成后自动重新使能 |
IRQF_NO_SUSPEND |
0x00000040 | 系统休眠时不关闭该中断 |
IRQF_TIMER |
0x00000080 | 标记为定时器中断,用于系统时钟 |
共享中断注意事项:使用
IRQF_SHARED 时,所有共享该中断线的驱动必须都设置此标志。中断处理函数必须检查硬件状态寄存器,确认中断是否来自本设备,若不是则立即返回 IRQ_NONE。
2.4 中断处理流程时序图
下图展示了从硬件中断触发到中断处理完成的核心流程,包含上半部( top half )与下半部( bottom half )的协作关系:
2.5 中断处理流程步骤清单
- 硬件中断触发:外设通过中断线向中断控制器发送中断信号。
- 中断控制器仲裁:中断控制器根据优先级选择最高优先级中断,向 CPU 发送中断请求。
- CPU 保存上下文:CPU 保存当前执行现场(寄存器、程序计数器等),跳转到中断向量表对应的入口地址。
- 上半部执行:调用
request_irq()注册的处理函数,完成紧急硬件操作(如清除中断标志、读取 FIFO 数据)。 - 调度下半部:上半部返回前,通过
schedule_work()或tasklet_schedule()调度下半部处理。 - CPU 恢复上下文:CPU 恢复被中断的进程上下文,继续执行原任务。
- 下半部执行:在合适的时机(如调度点、软中断),下半部处理函数在开中断环境下执行剩余工作。
性能指标:上半部执行时间应控制在微秒级,通常不超过 10μs;下半部执行时间可放宽到毫秒级,但应避免阻塞其他任务。workqueue 适合执行可能睡眠的长时间任务,tasklet 适合执行不可睡眠的短时间任务。