linux平台下 延迟工作队列实例

16800阅读 0评论2014-03-26 apple_guet
分类:LINUX

      工作队列(work queue)是Linux内核中将操作延期执行的一种机制。因为它们是通过守护进程在用户上下文执行,函数可以睡眠的时间,与内核是无关的。在内核版本2.5开发期间,设计了工作队列,用以替换此前的keventd机制。

        这种机制和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 就可以了

实例


上一篇:(一)Linux的电源管理架构
下一篇:input子系统(三)--input核心