workqueue和其他的bottom half最大的不同是它是运行在进程上下文中的,它可以睡眠,这和其他bottom half机制有本质的不同,大大方便了驱动工程师撰写中断处理代码。当然,驱动模块也可以自己创建一个kernel thread来解决defering work,但是,如果每个driver都创建自己的kernel thread,那么内核线程数量过多,这会影响整体的性能。因此,最好的方法就是把这些需求汇集起来,提供一个统一的机制,也就是传说中的work queue了
具体的流程是这样的 分为工作队列(workqueue)、工作(work)、工作线程池和工作队列渠道(pool_workqueue)、worker(工作线程)、worker_pool(工作线程池)
我们这里分析的是CMWQ机制 也就是concurrent-manage workqueue
工作队列
1、workqueue。定义如下:
struct workqueue_struct {
struct cpu_workqueue_struct *cpu_wq; -----per-cpu work queue struct
struct list_head list; ---workqueue list 负责加入链表
const char *name;
int singlethread; ----single thread or multi thread
int freezeable; ----和电源管理相关的一个flag
};
系统在启动的时候会调用init_workqueues函数来初始化几个默认的workqueue 通过create_workqueue()等一些接口创建
2.workqueue
struct workqueue_struct {
struct list_head pwqs; //所有的pool_workqueue 都挂入链表中
struct list_head list; //所有的workqueue挂入该链表
…
struct pool_workqueue __percpu *cpu_pwqs; -----指向per cpu的pool workqueue
struct pool_workqueue __rcu *numa_pwq_tbl[]; ----指向per node的pool workqueue
};
3、work
struct work_struct {
atomic_long_t data; //低比特位是标志位 高比特位是worker_pool的ID号或者其他
struct list_head entry;
work_func_t func; //调度函数 work被调度执行的时候就是调用这个函数
};
work_func_t 定义
typedef void (*work_func_t)(struct work_struct *work);
4、pool_workqueue
struct pool_workqueue {
struct worker_pool pool; / I: the associated pool */
struct workqueue_struct wq; / I: the owning workqueue */
int work_color; /* L: current color */
int flush_color; /* L: flushing color */
int refcnt; /* L: reference count */
int nr_in_flight[WORK_NR_COLORS];
/* L: nr of in_flight works */
int nr_active; /* L: nr