分类: LINUX
2015-08-26 10:25:52
原文地址:linux平台下 延迟工作队列实例 作者:apple_guet
这种机制和BH或Tasklets不同之处在于工作队列是把延期的工作交由一个内核线程去执行,因此工作队列的优势就在于它允许重新调度甚至睡眠。
每个工作队列多有一个数组,数据元素的数目与内核处理器core的数目相同,每个数据元素都列出来将要延期执行的任务。
对于每个工作队列来说,内核都会创建一个新的内核守护线程,延期任务使用上下文描述的等待队列机制,在守护进程的上下午执行。
先定义几个内核中使用工作队列时用到的术语方便后面描述。
如何使用工作队列哪?按如下步骤:
一. 声明一个工作队列
staticstruct workqueue_struct *test_wq;
二. 声明一个延期工作描述实例
static struct delayed_work test_dwq;
三. 声明并实现一个工作队列延迟处理函数
voiddelay_func(struct work_struct *work);
voiddelay_func(struct work_struct *work)
{
printk(KERN_INFO "My name isdelay_func!\n");
}
四. 初始化一个工作队列
test_wq = create_workqueue("test_wq");
五. 任务初始化
INIT_DELAYED_WORK(&test_dwq,delay_func);
六. 向工作队列提交工作项
queue_delayed_work(test_wq, &test_dwq, delay);
七. 取消工作队列中的工作项
int cancel_delayed_work(test_wq);
如果这个工作项在它开始执行前被取消,返回值是非零。内核保证给定工作项的执行不会在调用 cancel_delay_work 成功后被执行。 如果 cancel_delay_work 返回 0,则这个工作项可能已经运行在一个不同的处理器,并且仍然可能在调用 cancel_delayed_work 之后被执行。要绝对确保工作函数没有在 cancel_delayed_work 返回 0 后在任何地方运行,你必须跟随这个调用之后接着调用 flush_workqueue。在 flush_workqueue 返回后。任何在改调用之前提交的工作函数都不会在系统任何地方运行。
八. 刷新工作队列
flush_workqueue(test_wq);
九. 工作队列销毁
destroy_workqueue(test_wq);
涉及到的主要函数与结构体
一. 函数queue_delayed_work()
函数queue_delayed_work()是用于向工作队列提交delayed_work实例,确保在延期执行之前,至少会经过由delay指定的一段时间(以jiffies为单位)。
该函数首先创建一个由内核定时器,该定时器将在delayed jiffies之内超时。
二. 延期工作描述实例
structdelayed_work {
struct work_struct work; /* 将作为实例被queue_work或queue_work_delayed添加到一个工作队列*/
struct timer_list timer; /* 延迟时间*/
};
三. alloc_workqueue函数
struct workqueue_struct *alloc_workqueue(char *name, unsigned intflags, int max_active);
name:为工作队列的名字,而不像 2.6.36 之前实际是为工作队列服务的内核线程的名字。
Flag: 指明工作队列的属性,可以设定的标记如下:
· WQ_CPU_INTENSIVE:CPU 密集的工作项对并发级别并无贡献,换句话说,可运行的 CPU密集型工作项将不阻止其它工作项。这对于限定得工作项非常有用,因为它期望更多的 CPU 时钟周期,所以将它们的执行调度交给系统调度器。
· WQ_DRAINING:internal: workqueue is draining
· WQ_RESCUER :internal: workqueue has rescuer
· WQ_MAX_ACTIVE: I like 512, better ideas?
· WQ_MAX_UNBOUND_PER_CPU: 4 * #cpus for unbound wq
· WQ_DFL_ACTIVE:等于WQ_MAX_ACTIVE / 2,
max_active:决定了一个 wq 在 per-CPU 上能执行的最大工作项。比如 max_active 设置为 16 表示一个工作队列上最多 16 个工作项能同时在 per-CPU 上同时执行。当前实行中,对所有限定工作队列,max_active 的最大值是 512,而设定为 0 时表示是 256;而对于未限定工作队列,该最大值为:MAX[512,4 * num_possible_cpus() ],除非有特别的理由需要限流或者其它原因,一般设定为 0 就可以了
实例