作用:
内核中执行延迟执行或者异步执行的机制,运行在抢占上下文中,中断下半部分需要要睡眠,工作队列是唯一选择。
睡眠是指处理I/O数据、持有互斥锁、延迟,以及可能导致睡眠或将任务移出运行队列的所有其他任务,工作队列是内核中的一种机制,用于将需要延迟执行的任务排队,这些任务会在将来某个时刻由工作线程来执行。这对于不能在中断上下文中执行的任务或者不应该长时间阻塞的任务非常有用。
内核使用场景:
设备驱动程序:在设备驱动程序中,有些操作可能需要花费较长的时间来完成,例如硬盘读写、网络数据传输等。这些操作如果在中断处理程序中直接执行,可能会导致中断处理时间过长,影响系统的实时性。因此,可以将这些操作放入工作队列中,由内核在适当的时候异步执行。
文件系统:在文件系统中,有些操作可能需要在后台进行,例如数据的预读取、缓存的更新等。这些操作可以放入工作队列中,由内核在适当的时候异步执行。
网络协议栈:在网络协议栈中,有些操作可能需要在后台进行,例如数据的重传、连接的维护等。这些操作可以放入工作队列中,由内核在适当的时候异步执行。
内存管理:在内存管理中,有些操作可能需要在后台进行,例如页面的换出、缓存的清理等。这些操作可以放入工作队列中,由内核在适当的时候异步执行。
具体的例子:
功能:初始化一个内核工作项。
参数:void INIT_WORK(struct work_struct *work, void (*func)(struct work_struct *work))
#define __INIT_WORK(_work, _func, _onstack) \
do { \
__init_work((_work), _onstack); \
(_work)->data = (atomic_long_t) WORK_DATA_INIT(); \
INIT_LIST_HEAD(&(_work)->entry); \
(_work)->func = (_func); \
} while (0)
#endif
#define INIT_WORK(_work, _func) \
__INIT_WORK((_work), (_func), 0)
函数原型:struct workqueue_struct *alloc_workqueue(const char *fmt,unsigned int flags,int max_active, ...)
疑惑:工作队列是不是由一个内核线程单独处理?- - 由内核kworker来处理。
功能: 初始化一个工作队列。
参数:
include/linux/workqueue.h
中。...
:可变参部分用于传递fmt格式化字符串对应的参数。函数原型:void destroy_workqueue(struct workqueue_struct *wq)
功能:安全的终止一个工作队列,会等待所有正在处理事项完成。
参数:
函数原型:void flush_workqueue(struct workqueue_struct *wq)
功能:确保任何需要被调度执行的工作都运行完成,这个函数会休眠,直到所有在进入排队的工作项都已完成执行,新添加的工作项不会活锁?
参数:
/**
* flush_workqueue - ensure that any scheduled work has run to completion.
* @wq: workqueue to flush
*
* This function sleeps until all work items which were queued on entry
* have finished execution, but it is not livelocked by new incoming ones.
*/
函数原型:static inline bool queue_work(struct workqueue_struct *wq, struct work_struct *work)
功能:将工作项work添加到工作队列workqueue中,将工作项排队到提交它的CPU上,但是如果该CPU停止工作,那么这个工作项可以由另一个CPU处理。
参数:
返回值:
/**
* queue_work - queue work on a workqueue
* @wq: workqueue to use
* @work: work to queue
*
* Returns %false if @work was already on a queue, %true otherwise.
*
* We queue the work to the CPU on which it was submitted, but if the CPU dies
* it can be processed by another CPU.
*/
static inline bool queue_work(struct workqueue_struct *wq,
struct work_struct *work)
{
return queue_work_on(WORK_CPU_UNBOUND, wq, work);
}
在内核md模块中有相关的使用示例。
static struct workqueue_struct *md_misc_wq; // 定义了一个md杂项工作队列。
// mddev用来标识一个软raid设备,包含一个del_work的成员。
struct mddev {
struct work_struct del_work; /* used for delayed sysfs removal */
}
// 初始化工作队列。
md_misc_wq = alloc_workqueue("md_misc", 0, 0);
// 销毁工作队列。
destroy_workqueue(md_misc_wq);
// 初始化del_work工作项,绑定调度执行时函数md_start_sync。
INIT_WORK(&mddev->del_work, md_start_sync);
// 将工作项添加进入md_misc_wq工作队列。
queue_work(md_misc_wq, &mddev->del_work);