queue_work 简介

queue_work 是 Linux 内核中 workqueue 机制的一个关键函数,用于将工作(work)提交到工作队列(workqueue)中异步执行。

workqueue 基本概念

workqueue 是 Linux 内核中自 2.6 版本引入的一种任务执行机制,与 softirq 和 tasklet 并称为下半部(bottom half)三剑客[1]。与其他下半部机制不同,workqueue 在进程上下文中执行,这意味着它可以睡眠,这是它的一个重要特性[2]。

workqueue 的核心思想是分离任务(work)的发布者和执行者[1]。当需要执行任务时,构造一个 work,通过 queue_work 函数将其放入相应的 workqueue,由 workqueue 所绑定的 worker 线程(实际上是内核线程)去执行。

queue_work 工作原理

queue_work 函数的主要工作是将一个 work 结构体添加到指定的工作队列中,并通知相应的 worker 线程来处理它。其基本流程如下:

  1. 检查 work 的状态:首先通过 test_and_set_bit 原子操作检查 WORK_STRUCT_PENDING_BIT 位,确保该 work 不会被重复添加[2][5]。

  2. 调用 __queue_work:如果 work 不处于 pending 状态,则调用 __queue_work 函数将 work 挂入工作队列并通知 worker 线程池来处理[5]。

  3. 唤醒 worker 线程:queue_work 会调用 wake_up 来唤醒休眠在 cwq->more_work 上的 worker_thread 进程[3]。

工作队列的处理流程

当 work 被添加到工作队列后,worker 线程的处理流程大致如下:

  1. 从该 worker 线程对应的 work list 中摘下一个 work[2]。
  2. 清除 pending 标志[2]。
  3. 执行该 work 的回调函数(callback function)[2]。

并发处理

在 2.6.36 版本之前,workqueue 和 worker 的对应关系是二元化的:要么使用 Multi Threaded (MT) workqueue 每个 CPU 一个 worker,要么使用 Single Threaded (ST) workqueue 整个系统只有一个 worker[1]。

在 2.6.36 版本中引入了 CMWQ(Concurrency Managed Workqueue)机制,通过引入 worker pool 概念,实现了对 workqueue 机制中生产者(workqueue)和消费者(worker)的解耦[1]。

对于 single thread workqueue,由于只有一个 worklist 和一个线程,work 的回调函数是严格串行执行的。而对于 per cpu workqueue,各个 CPU 上都有一个 worker 线程及其要处理的 work list,因此可能会有多个 work 在多个 CPU 上并行执行[2]。

使用示例

使用 workqueue 的基本步骤如下:

  1. 创建或获取一个工作队列:

    struct workqueue_struct *wq = create_workqueue("my_queue");
    

    或使用系统默认的工作队列 system_wq

  2. 定义并初始化一个 work 结构体:

    DECLARE_WORK(my_work, my_work_handler);
    

    或动态初始化:

    INIT_WORK(&my_work, my_work_handler);
    
  3. 提交 work 到工作队列:

    queue_work(wq, &my_work);
    

    或指定 CPU:

    queue_work_on(cpu, wq, &my_work);
    

通过这种方式,可以将耗时的工作推迟到工作队列中异步执行,避免阻塞当前执行路径。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值