如何使用Linux工作队列workqueue

本文档的Copyleft归rosetta所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性。

参考资料:《Linux设备驱动程序》第3版 LDD3e, LKD3e, 《 Linux per-CPU实现分析 》,linux-2.6.27,irq_balance

2,使用工作队列
        *编译时静态创建,因为暂时用不到也就没去看具体实现过程和用法。
        #define DECLARE_WORK(name, void(*func)(void *), void *data);
        其使用的默认处理函数为work_handler(void *data)。
        使用schedule_work(&work)进行工作调度。
        *动态创建
        INIT_WORK(struct work_struct *work,void(*func)(void *), void *data);
        比如如下代码
        static DEFINE_PER_CPU(struct sk_buff_head, bs_cpu_queues);
        int netif_receive_skb(struct sk_buff *skb)//接收到网卡数据
        {
                ……
                ……
                static inline int bs_dispatch(struct sk_buff *skb)//分发网卡数据
                {
                         struct sk_buff_head *q;
                        q = &per_cpu(bs_cpu_queues, cpu);//从CPU为cpu处取一个sk_buff_head数据结构
                        //把数据skb插入到双向循环链表q中。这样子这个q就是待处理的数据了。

                        bs_works = &per_cpu(bs_works, cpu);//从CPU为cpu处取一个work_struct结构
                        if (!bs_works->func) {//假如当前工作处理函数指针为空
                                 INIT_WORK(bs_works, bs_func, q);//创建工作队列,工作队列函数指为bs_func,处理的数据为q。
                                 queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), bs_works);//在CPU编号为cpu的默认队列keventd_wq中插入一个bs_works工作任务。具体看下面。                         
                        }
                 }
                ……
                ……
        } 

3,创建新的工作队列已经在《Linux工作队列workqueue实现分析》讲过了,是通过create_workqueue实现,这里不再重复。

4,工作调度
        *默认工作队列处理函数
        void work_handler(void *data)//在好几个版本的内核里没有发现这个函数或者宏定义,只找到了work_handlers,它其实是个函数指针数组,具体实现没仔细看,大概就是为初始化一些函数,再看时机进行调度。
        使用schedule_work()对默认的event队列进程调度。
        *调度新创建的工作队列
        int queue_work(struct workqueue_struct *wq, struct work_struct *work)
        从其参数可知,它是对某种类型的任务进行工作调度,即这种类型的每个CPU中的工作者线程的每个体work_struct都要被调度。
        由于上面使用的是per_cpu_ptr(keventd_wq->cpu_wq, cpu),其返回的是CPU为cpu的keventd_wq->cpu_wq workqueue_struct结构,即默认的工作队列,所以上面其实可以使用schedule_work(&work)进行调度。使用queue_work一般是自己指定自行创建的工作队列wq,这个工作队列由 create_workqueue()创建返回。

相关推荐