工作队列

来源:互联网 发布:淘宝买家订单数据诈骗 编辑:程序博客网 时间:2024/05/17 09:33
工作队列是一种将工作推后执行的机制。
工作队列可以把工作推后,交由一个内核线程去执行,它是中断下半部分实现的一种形式,
而且它总是会在进程上下文中执行。这样,通过工作队列执行的代码能占尽进程上下文的所有优势。
最重要的就是工作队列允许重新调度甚至是睡眠。

工作的结构体声明
typedef void (*work_func_t)(struct work_struct *work);struct work_struct {atomic_long_t data;#define WORK_STRUCT_PENDING 0/* T if work item pending execution */#define WORK_STRUCT_FLAG_MASK (3UL)#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)struct list_head entry;work_func_t func;#ifdef CONFIG_LOCKDEPstruct lockdep_map lockdep_map;#endif};#define WORK_DATA_INIT()ATOMIC_LONG_INIT(0)struct delayed_work {struct work_struct work;struct timer_list timer;};

定义并初始化一个工作
#define DECLARE_WORK(n, f)\struct work_struct n = __WORK_INITIALIZER(n, f)#define __WORK_INITIALIZER(n, f) {\.data = WORK_DATA_INIT(),\.entry= { &(n).entry, &(n).entry },\.func = (f),\__WORK_INIT_LOCKDEP_MAP(#n, &(n))\}


定义并初始化一个延迟的工作
#define DECLARE_DELAYED_WORK(n, f)\struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f)#define __DELAYED_WORK_INITIALIZER(n, f) {\.work = __WORK_INITIALIZER((n).work, (f)),\.timer = TIMER_INITIALIZER(NULL, 0, 0),\}

不定义仅初始化一个工作
#define INIT_WORK(_work, _func)\do {\(_work)->data = (atomic_long_t) WORK_DATA_INIT();\INIT_LIST_HEAD(&(_work)->entry);\PREPARE_WORK((_work), (_func));\} while (0)

不定义仅初始化一个延迟的工作
#define INIT_DELAYED_WORK(_work, _func)\do {\INIT_WORK(&(_work)->work, (_func));\init_timer(&(_work)->timer);\} while (0)
/* * initialize a work item's function pointer */#define PREPARE_WORK(_work, _func)\do {\(_work)->func = (_func);\} while (0)#define PREPARE_DELAYED_WORK(_work, _func)\PREPARE_WORK(&(_work)->work, (_func))

工作队列的结构体

struct workqueue_struct {struct cpu_workqueue_struct *cpu_wq;struct list_head list;const char *name;int singlethread;int freezeable;/* Freeze threads during suspend */int rt;#ifdef CONFIG_LOCKDEPstruct lockdep_map lockdep_map;#endif};/* * The per-CPU workqueue (if single thread, we always use the first * possible cpu). */struct cpu_workqueue_struct {spinlock_t lock;struct list_head worklist;wait_queue_head_t more_work;struct work_struct *current_work;struct workqueue_struct *wq;struct task_struct *thread;} ____cacheline_aligned;


创建一个工作队列
#define create_workqueue(name) __create_workqueue((name), 0, 0, 0)
该函数会创建一个内核线程,该线程的名称就是传递的参数name;另外还会返回一个
动态创建的工作队列的指针;最后让该线程进行起来。

/** * schedule_work - put work task in global workqueue * @work: job to be done * * Returns zero if @work was already on the kernel-global workqueue and * non-zero otherwise. * * This puts a job in the kernel-global workqueue if it was not already * queued and leaves it in the same position on the kernel-global * workqueue otherwise. * 这将把一个工作加入到内核全局变量工作队列中,如果没有加入成功,那么将在 * 相同的地方leaves it. */ static struct workqueue_struct *keventd_wq;int schedule_work(struct work_struct *work){return queue_work(keventd_wq, work);}
说明:
该函数将工作[work]加入到全局的工作队列[keventd_wq]中。
如果成功返回0,否则返回非0;

/** * schedule_delayed_work - put work task in global workqueue after delay * @dwork: job to be done * @delay: number of jiffies to wait or 0 for immediate execution * * After waiting for a given time this puts a job in the kernel-global * workqueue. */int schedule_delayed_work(struct delayed_work *dwork,unsigned long delay){return queue_delayed_work(keventd_wq, dwork, delay);}
说明:
该函数将延迟delay长的时间后再把工作[work]加入到全局的工作队列[keventd_wq]中。
@dwork: 将要加入的工作
@delay: 延迟的时间,如果为0表示不延迟,立即运行


总结:
工作队列的用法:
1> 定义并初始化一个工作,可以用以下两个方法:
a) DECLARE_WORK(n, f)

b) INIT_WORK(_work, _func)


       e.g.     DECLARE_WORK (zwmy_work, zwmy_test_func);

2> 如果用内核初始化好的工作者线程的话,那么只需要调用下面这个函数:

       schedule_work(struct work_struct *work);

e.g.     schedule_work(&zwmy_work);

   
3> 如果需要自定义一个工作者线程的话,那么:
   a) 调用下面的函数创建一个工作者线程,创建一个工作队列

 create_workqueue(name)

e.g. struct workqueue_struct * zwmy_wq;

zwmy_wq = create_workqueue(&zwmy_work);

   b) 调用下面的函数将工作加入到工作队列中

queue_work(struct workqueue_struct *wq, struct work_struct *work);

        e.g.      queue_work(zwmy_wq,  &zwmy_work);




0 0