内核版本:Linux-2.6.32.2
工作队列类似于tasklet,它允许内核代码请求某个函数在将来被执行(不是立即执行)。
工作队列相关API定义在<linux/workqueue.h>中。要使用工作队列有两种方式,一是自己创建一个工作队列;二是使用内核提供的工作队列(共享方式)。
一、我们先来看自己创建工作队列的方式
工作队列使用结构体struct workqueue_struct描述,要创建一个工作队列有两个API,即create_workqueue和create_singlethread_workqueue,原型如下:
struct workqueue_struct *create_workqueue(const char *name); struct workqueue_struct *create_singlethread_workqueue(const char *name);例如:
struct workqueue_struct *keventd_wq; keventd_wq = create_workqueue("events");create_workqueue函数会在系统中的每个处理器上创建一个线程(多线程),而create_singlethread_workqueue只是创建一个单一的线程,如果单个线程足够使用,那么应该使用create_singlethread_workqueue函数。
DECLARE_WORK(name, void (*func)(void *)); INIT_WORK(struct work_struct *work, void (*func)(void *));DECLARE_WORK宏用于静态定义一个work_struct。而INIT_WORK宏用于动态初始化一个work_struct。
延时任务使用INIT_DELAYED_WORK宏初始化。
INIT_DELAYED_WORK(struct delayed_work, void (*func)(void *));
int queue_work(struct workqueue_struct *wq, struct work_struct *work); int queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, unsigned long delay);这两个函数都会将任务提交到工作队列中,使用queue_delayed_work函数,则提交的任务至少延时由参数delay指定的时间才被执行。
int cancel_delayed_work(struct work_struct *work);如果任务在被执行之前取消,那么cancel_delayed_work函数返回非零值,调用该函数之后内核会确保被取消的任务不被执行。但是返回0,则表示任务已经被执行,因此调用cancel_delayed_work函数后,任务有可能仍在运行,所以为了确保任务测地被取消,需要调用flush_workqueue函数。
void flush_workqueue(struct workqueue_struct *wq);
void destroy_workqueue(struct workqueue_struct *wq);
内核在初始化时创建了一个工作队列"events",这个工作队列是共享的,所以我们可以向这个队列提交简单的任务处理。
由于这个工作队列已经被创建好了,所以不再需要我们去创建了,直接往工作队列提交任务就可以了,内核为我们提供了相关API:
int schedule_work(struct work_struct *work); int schedule_delayed_work(struct delayed_work *work, unsigned long delay);而这两个函数最终还是调用的前面内核提供的函数,只是工作队列为内核中的keventd_wq。
void flush_scheduled_work(void);