工作队列
- 工作队列由内核线程执行,在进程上下文中执行。
- 工作队列允许重新调度甚至是睡眠
- 在工作队列和软中断/tasklet中做出选择非常容易。如果推后执行的任务需要睡眠,就选择工作队列。不需要睡眠,就选择软中断或tasklet
- 唯一能在进程上下文中运行、睡眠的下半部机制。在需要获得大量内存、需要获取信号量、需要执行阻塞式的I/O操作时,工作队列会非常有用。
工作队列的实现
- 工作者线程:创建的内核线程负责执行由内核其他部分排到队列里的任务
- 缺省的工作者线程叫做events/n,这里的n是处理器编号
- 表示线程的数据结构
工作者线程用workqueue_struct结构标识
struct workqueue_struct{
struct cpu_workqueue_struct cpu_wq[NR_CPUS];
…
}
每个处理器,每个工作者线程对应一个cpu_workqueue_struct结构体。
struct cpu_workqueue_struct {
spinlock_t lock;
struct workqueue_struct *wq; //关联工作队列结构
}
工作用work_struct结构体表示
struct work_struct{
atomic_long_t data;
struct list_head entry;
work_fun_t func;
- 使用工作队列
缺省的events工作队列
<a>创建推后的工作:
编译时静态创建 DECLARE_WORK(name, void (*func) (void *), void *data);
动态创建 INIT_WORK(struct work_struct *work, void (*func) (void *), void *data);
<b>工作队列处理函数:
void work_handler(void *data)
<c>对工作进行调度:
schedule_work(&work);
schedule_delayed_work(&work, delay);
<d>刷新操作:在继续下一步工作之前,必须保证一些操作已经执行完毕。
void flush_scheduled_work(void);
函数会一直等待,知道队列中的所有对象都被执行才返回。该函数不取消任何延迟执行的工作。取消延迟执行工作应调用:
Int cancel_delayed_work(struct work_struct *work);
创建新的工作队列
<a>创建自己的工作队列
struct workqueue_struct *create_workqueue(const char *name);
<b>对工作进行调度
Int queue_work(struct workqueue_struct *wq, struct work_struct *work)
Int queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay)
<c>刷新指定队列
Flush_workqueue(struct workqueue_struct *wq);