在Linux内核中,处理中断时通常分为上半部(top half)和下半部(bottom half)。上半部处理紧急任务,需要快速执行并退出;下半部处理耗时操作,可以稍后执行。以下是Linux驱动中实现中断下半部的三种主要方法:
软中断是内核提供的一种延迟执行机制,具有以下特点: - 执行在中断上下文中,不能睡眠 - 同一类型的软中断可以在不同CPU上并行运行 - 需要静态注册,不能动态分配
使用方法:
#include <linux/interrupt.h>
// 定义软中断
DECLARE_SOFTIRQ(MY_SOFTIRQ, my_softirq_handler);
// 注册软中断
open_softirq(MY_SOFTIRQ, my_softirq_handler);
// 触发软中断
raise_softirq(MY_SOFTIRQ);
任务队列是基于软中断实现的更高层抽象,特点包括: - 同一任务队列在多个CPU上不会并行执行 - 使用简单,可以动态创建 - 同样不能睡眠
使用方法:
#include <linux/interrupt.h>
// 定义任务队列处理函数
void my_tasklet_func(unsigned long data);
// 声明任务队列
DECLARE_TASKLET(my_tasklet, my_tasklet_func, data);
// 在中断处理函数中调度任务队列
tasklet_schedule(&my_tasklet);
工作队列是唯一可以在进程上下文中执行的中断下半部机制: - 可以睡眠 - 执行在进程上下文 - 适合处理耗时较长的任务
使用方法:
#include <linux/workqueue.h>
// 定义工作队列处理函数
void my_work_handler(struct work_struct *work);
// 声明工作队列
DECLARE_WORK(my_work, my_work_handler);
// 在中断处理函数中调度工作队列
schedule_work(&my_work);
在实际驱动开发中,任务队列和工作队列是最常用的两种方法,软中断通常在内核核心代码中使用较多。