工作队列 workqueue

工作队列是Linux内核实现延后任务的一种机制,用于避免过多的内核线程导致的性能影响。它包括workqueue_struct结构和work_struct工作元素。初始化work_struct后,可以将其提交到工作队列,由worker_thread内核线程执行。工作队列的创建和销毁以及工作元素的提交是其核心操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

工作队列是内核用于进行延后工作的一种方式。当然驱动模块中使用之前提到的kernel thread就可以完成延后工作了,但是如果每个驱动模块都创建自己的kernel thread,那么内核线程数量过多,这会影响整体的性能。因此,最好的方法就是把这些需求汇集起来,提供一个统一的机制,也就是workqueue了。

它的结构是workqueue_struct;

和工作队列息息相关的是工作元素work_struct,毕竟队列只是一个容器罢了,光有队列是不能干什么活的,它定义在kernel-4.9/include/linux/workqueue.h

struct work_struct {
	atomic_long_t data;
	struct list_head entry;
	work_func_t func;
#ifdef CONFIG_LOCKDEP
	struct lockdep_map lockdep_map;
#endif
};

work_struct的初始化,定义在kernel-4.9/include/linux/workqueue.h中;这个方法的用途是将对应的work_struct变量和函数地址建立联系。

#define INIT_WORK(_work, _func)						\
	__INIT_WORK((_work), (_func), 0)

这里有一个比较奇怪的地方,因为一些资料里面提到的INIT_WORK方法有第三个参数data,然而在kerenl-4.9下的并没有,于是再查看一了下kernel-3.18的代码;

#define INIT_WORK(_work, _func)						\
	do {								\
		__INIT_WORK((_work), (_func), 0);			\
	} while (0)

虽然有些不同,但是,依然没有第三个参数。感觉应该早前版本的形式,如2.6之类的。

通常来说在初始化之前,得先分配个内存;

struct work_struct *hardwork;

hardwork = kamlloc(sizeof(struct work_struct), GFP_KERNEL);

INIT_WORK(hardwork, func);

在真正使其工作前,还得把工作队列给初始化了:

#define create_workqueue(name)						\
	alloc_workqueue("%s", __WQ_LEGACY | WQ_MEM_RECLAIM, 1, (name))
#define create_freezable_workqueue(name)				\
	alloc_workqueue("%s", __WQ_LEGACY | WQ_FREEZABLE | WQ_UNBOUND |	\
			WQ_MEM_RECLAIM, 1, (name))
#define create_singlethread_workqueue(name)				\
	alloc_ordered_workqueue("%s", __WQ_LEGACY | WQ_MEM_RECLAIM, name)

create_singlethread_workqueue创建工作队列即使对于多CPU系统,内核也只负责在一个cpu上创建一个worker_thread内核线程;而使用create_workqueue创建工作队列对于多CPU系统,内核将会在每个CPU上创建一个worker_thread内核线程,使得线程处理的事务能够并行化。

用完之后得回收,下面是用于销毁workqueue的函数;

extern void destroy_workqueue(struct workqueue_struct *wq);

有了队列和元素,下一步就是把元素提交给队列;

/**
 * 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);
}

/**
 * schedule_work - put work task in global workqueue
 * @work: job to be done
 *
 * Returns %false if @work was already on the kernel-global workqueue and
 * %true 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.
 */
static inline bool schedule_work(struct work_struct *work)
{
	return queue_work(system_wq, work);
}

最后就可以坐等work_struct中关联的函数被调用了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值