Linux 驱动中 Timer / Tasklet / Workqueue 的作用与对比

发布于:2025-07-17 ⋅ 阅读:(18) ⋅ 点赞:(0)

Linux 驱动中 Timer / Tasklet / Workqueue 的作用与对比

🧩 1. 使用场景概览(对比表)

机制 执行上下文 是否可睡眠 使用场景 常用接口
Timer 中断上下文 ❌ 不可睡眠 延迟执行(如防抖、超时处理) add_timer()
Tasklet 软中断上下文 ❌ 不可睡眠 中断后的轻量快速处理 tasklet_schedule()
Workqueue 进程上下文 ✅ 可睡眠 可阻塞、耗时操作(如 I/O) schedule_work()

🧠 2. 各机制作用详解

🔧 Timer(定时器)

  • 作用:延迟执行某个函数,常用于按键防抖、超时控制等
  • 上下文:中断上下文(不可睡眠)
  • 示例
    struct timer_list my_timer;
    timer_setup(&my_timer, my_timer_handler, 0);
    mod_timer(&my_timer, jiffies + msecs_to_jiffies(20));
    

⚡ Tasklet(软中断)

  • 作用:将中断处理函数中不能做的工作,延后到软中断上下文处理。
  • 上下文:软中断上下文(不可阻塞)。
示例:
struct tasklet_struct tasklet;
DECLARE_TASKLET(my_tasklet, tasklet_handler, data);
tasklet_schedule(&my_tasklet);

🧵 Workqueue(工作队列)

  • 作用:将任务放到内核线程中执行,可以使用阻塞操作,适合复杂或耗时的任务。
  • 上下文:进程上下文(可阻塞)。
示例:
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示例:
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;
}

网站公告

今日签到

点亮在社区的每一天
去签到