workqueue使用小结

本文介绍了Linux内核中workqueue机制的两种使用方式:一是利用系统默认提供的system_wq;二是自定义创建workqueue。详细解释了如何初始化、调度、取消及销毁workqueue,并提供了具体的代码示例。

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

workqueue是一种中断的下半部机制,其可以提供一个进程上下文来推迟工作。
主要有两种使用方法,一种是使用系统默认提供的workqueue,即system_wq
其使用的方法如下:
		if (remove) {
			INIT_WORK(&entry->delete_netdev, delete_netdev);
			schedule_work(&entry->delete_netdev);
		}
从schedule_work的源码可以看出是使用的system_wq
static inline bool schedule_work(struct work_struct *work)
{
	return queue_work(system_wq, work);
}
通过cancel_work_sync()来取消一个workqueue
在int __init workqueue_init_early(void)中有申请system_wq和system_highpri_wq
而每个cpu都有这两个workqueue,所以percpu定义如下:
static DEFINE_PER_CPU_SHARED_ALIGNED(struct worker_pool [NR_STD_WORKER_POOLS], cpu_worker_pools);

除了提供INIT_WORK外,其他使用system_wq的函数为INIT_DELAYED_WORK,INIT_DEFERRABLE_WORK
第二种是自己通过alloc_workqueue()来自己创建一个workqueue.
例如:创建一个自己的workqueue
	iommu_wq = alloc_workqueue("amd_iommu_v2", WQ_MEM_RECLAIM, 0);
	if (iommu_wq == NULL)
		goto out;

flush queue:
	flush_workqueue(iommu_wq);

运行这个queue	
	queue_work(iommu_wq, &fault->work);
	
销毁queue
		destroy_workqueue(iommu_wq);


### Go语言 Workqueue 的实现与用法 #### 工作队列的核心概念 `workqueue` 是 Kubernetes 中 `client-go` 提供的一个工具库,主要用于管理异步任务的工作队列。它通过提供线程安全的操作来支持高并发场景下的任务调度和执行。 核心接口定义如下: ```go type Interface interface { Add(item interface{}) Len() int Get() (item interface{}, shutdown bool) Done(item interface{}) ShutDown() ShuttingDown() bool } ``` 上述代码展示了 `Interface` 接口的定义[^1],它是所有具体队列类型的基类,提供了基本的功能操作。 #### FIFO 队列的具体实现 FIFO(First In First Out)是最常见的队列类型之一,在 `workqueue` 库中实现了基于 slice 和 map 数据结构的任务存储逻辑。以下是其关键字段及其作用: - **queue**: 存储待处理的任务列表。 - **dirty**: 用于去重,确保同一任务不会重复进入队列。 - **processing**: 记录当前正在处理的任务状态,防止重复处理。 这些字段的设计使得即使在高并发环境下,也能保证任务的一致性和唯一性[^4]。 #### 使用示例 下面展示了一个简单的例子,演示如何创建并使用一个 FIFO 类型的工作队列: ```go package main import ( "fmt" "time" workqueue "k8s.io/client-go/util/workqueue" ) func processItem(item interface{}) error { fmt.Printf("Processing item: %v\n", item) return nil } func main() { queue := workqueue.New() for i := 0; i < 5; i++ { item := fmt.Sprintf("task-%d", i) queue.Add(item) // 添加任务到队列 } go func() { for { if queue.ShuttingDown() { break } item, shutdown := queue.Get() if shutdown { break } defer queue.Done(item) err := processItem(item.(string)) if err != nil { fmt.Println(err) } else { fmt.Println("Task processed successfully.") } } }() time.Sleep(2 * time.Second) queue.ShutDown() // 关闭队列 } ``` 在这个程序中,我们首先初始化了一个新的 FIFO 队列实例,并向其中添加了一些模拟任务。随后启动一个新的 Goroutine 来不断从队列中取出任务并调用回调函数对其进行处理。最后当所有任务完成或者接收到关闭信号时退出循环[^2]。 #### RateLimitingQueue 特殊功能扩展 除了普通的 FIFO 行为外,Kubernetes 还引入了一种名为 `RateLimitingQueue` 的特殊队列形式,它可以对频繁失败的任务施加速率限制策略。这种设计特别适合于那些可能由于暂时错误而多次尝试重新加入队列的情况。 它的额外方法包括但不限于以下几个方面: - **When**: 返回某个特定条目应等待多久才能再次被尝试。 - **Forget**: 清除某项的历史失败记录以便未来不再对其应用延迟惩罚。 - **NumRequeues**: 查询给定项目的累计重试次数[^3]。 这允许开发者更灵活地控制异常情况下的行为模式而不至于让整个系统陷入死锁或过载状态之中。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值