Linux 驱动中 Timer / Tasklet / Workqueue 的作用与对比
🧩 1. 使用场景概览(对比表)
机制 | 执行上下文 | 是否可睡眠 | 使用场景 | 常用接口 |
---|---|---|---|---|
Timer | 中断上下文 | ❌ 不可睡眠 | 延迟执行(如防抖、超时处理) | add_timer() 等 |
Tasklet | 软中断上下文 | ❌ 不可睡眠 | 中断后的轻量快速处理 | tasklet_schedule() |
Workqueue | 进程上下文 | ✅ 可睡眠 | 可阻塞、耗时操作(如 I/O) | schedule_work() 等 |
🧠 2. 各机制作用详解
🔧 Timer(定时器)
-
作用:延迟执行某个函数,常用于按键防抖、超时控制等
-
上下文:中断上下文(不可睡眠)
-
示例 :
cstruct timer_list my_timer; timer_setup(&my_timer, my_timer_handler, 0); mod_timer(&my_timer, jiffies + msecs_to_jiffies(20));
⚡ Tasklet(软中断)
- 作用:将中断处理函数中不能做的工作,延后到软中断上下文处理。
- 上下文:软中断上下文(不可阻塞)。
示例:
c
struct tasklet_struct tasklet;
DECLARE_TASKLET(my_tasklet, tasklet_handler, data);
tasklet_schedule(&my_tasklet);
🧵 Workqueue(工作队列)
- 作用:将任务放到内核线程中执行,可以使用阻塞操作,适合复杂或耗时的任务。
- 上下文:进程上下文(可阻塞)。
示例:
c
struct work_struct work; // 定义工作队列结构体
void work_handler(struct work_struct *work) {
printk(KERN_INFO "Work handler executed\n");
}
INIT_WORK(&my_work, work_handler); // 初始化工作队列,绑定处理函数work_handler
schedule_work(&my_work); // 将工作队列加入调度队列
三种方式调用func示例:
c
static irqreturn_t gpio_key_isr(int irq, void *dev_id)
{
struct gpio_key *gpio_key = dev_id;
//printk("gpio_key_isr key %d irq happened\n", gpio_key->gpio);
tasklet_schedule(&gpio_key->tasklet);
mod_timer(&gpio_key->key_timer, jiffies + HZ/50);
schedule_work(&gpio_key->work);
// schedule_work:调度工作队列(需在非原子上下文中调用)
return IRQ_HANDLED;
}