1 "工作队列"用途
工作队列用途跟tasklet相似,在中断处理时
将一些非紧急的任务留到工作队列中完成,而紧急的任务则在硬中断服务程序中完成。
但工作队列与tasklet还是有很大的区别:
1)工作队列函数在一个特殊内核进程的上下文中运行;
2)tasklet会在很短的时间段内很快执行,且以原子模式执行;
而工作队列函数具有更长的延迟并且不需要原子模式;
3)工作队列函数可以休眠;
2 "工作队列"结构
注意:在2.6.20之后,工作队列的数据结构发生了不少变化,这里列出的接口与数据结构是基于3.2.1的。
-
#include
-
struct workqueue_struct {/*定义在kernel/workqueue.c*/}; /*工作队列结构*/
-
-
struct work_struct { /*向工作队列提交一个任务的任务结构*/
-
atomic_long_t data;
-
struct list_head entry;
-
work_func_t func; /*work_func_t 定义如下*/
-
/*省略其他成员变量*/
-
}
-
typedef void (*work_func_t)(struct work_struct *work);
3 "工作队列"接口
这里只列出一些重要的接口,如果想查看更多接口,可参看"linux/workqueue.h"文件。
3.1 创建工作队列
-
/*这两个是宏,使用时name不用加双引号,这里这样写只是更好地表达该宏的用途*/
-
struct workqueue_struct *create_workqueue(const char *name) /*在系统中的每个处理器上
-
为该工作队列创建专用线程*/
-
struct workqueue_struct *create_singlethread_workqueue(const char *name) /*只创建一个
-
专用线程*/
3.2 创建工作(work_struct)
-
DECLARE_WORK(name,func); /*定义名为name的work_struct类型变量,使用时name不用加双引号,
-
func是work_func_t类型*/
-
-
INIT_WORK(struct work_struct *work,work_func_t func); /*添充work变量,首次构造该结构时使用*/
-
INIT_DELAYED_WORK(struct work_struct *work,work_func_t func);
-
PREPARE_WORK(struct work_struct *work,work_func_t func); /*如果工作已提交到工作队列时,
-
而只需修改该结构时使用*/
3.3 提交工作到工作队列
-
int queue_work(struct workqueue_struct *wq, struct work_struct *work);
-
int queue_delayed_work(struct workqueue_struct *wq, struct_work *work,
-
unsigned long delay); /*工作至少会被延迟delay后被执行*/
3.4 取消工作
-
int cancel_delayed_work(struct work_struct *work); /*如果工作在开始执行前被取消,则返回非零值*/
-
void flush_workqueue(struct workqueue_struct *wq); /*该函数返回后,任何在该函数调用之前
-
被提交的工作都不会在系统任何地方运行*/
3.5 销毁"工作队列"
-
void destroy_workqueue(struct workqueue_struct *queue);
4 共享队列
如果对工作队列使用不是很频繁的话,则可以使用内核提供的共享的默认队列;需要注意的是,使用该共享队列时不应该长期独占它,而且任务可能需要等待更长的时间后才被执行;一般情况下,推荐使用共享队列。
共享队列接口
-
int schedule_work(struct work_struct *work); /*提交工作任务到共享队列*/
-
int schedule_delayed_work(struct work_struct *work,unsigned long delay);
-
void flush_scheduled_work(void);
5 示例代码
这里只是演示如何使用“工作队列”,并没有在中断处理中使用。
5.1 自己创建工作队列
workqueue.rar
-
#include <linux/module.h>
-
#include <linux/init.h>
-
#include <linux/workqueue.h>
-
-
MODULE_LICENSE("Dual BSD/GPL");
-
MODULE_AUTHOR("Kozo");
-
-
struct my_struct{
-
char *name;
-
struct work_struct my_work;
-
};
-
-
static void display(struct work_struct *work)
-
{
-
struct my_struct *my_name = container_of(work,struct my_struct, my_work);
-
printk(KERN_DEBUG"name = %s\n",my_name->name);
-
}
-
-
static struct workqueue_struct *my_wq; /*注意要全局变量*/
-
static struct my_struct my_name; /*注意要全局变量*/
-
-
static int __init demo_init(void)
-
{
-
my_wq = create_workqueue("my wq");
-
my_name.name = "Kozo";
-
INIT_WORK(&(my_name.my_work), display);
-
queue_work(my_wq,&(my_name.my_work));
-
return 0;
-
}
-
-
static void __exit demo_exit(void)
-
{
-
printk(KERN_DEBUG"Goodbye\n");
-
destroy_workqueue(my_wq);
-
}
-
module_init(demo_init);
-
module_exit(demo_exit);
5.2 使用共享队列
sharequeue.rar
-
#include <linux/module.h>
-
#include <linux/init.h>
-
#include <linux/workqueue.h>
-
-
MODULE_LICENSE("Dual BSD/GPL");
-
MODULE_AUTHOR("Kozo");
-
-
struct my_struct{
-
char *name;
-
struct work_struct my_work;
-
};
-
-
static void display(struct work_struct *work)
-
{
-
struct my_struct *my_name = container_of(work,struct my_struct, my_work);
-
printk(KERN_DEBUG"name = %s\n",my_name->name);
-
}
-
-
static struct my_struct my_name;
-
-
static int __init demo_init(void)
-
{
-
my_name.name = "Kozo";
-
INIT_WORK(&(my_name.my_work), display);
-
schedule_work(&(my_name.my_work));
-
return 0;
-
}
-
-
static void __exit demo_exit(void)
-
{
-
printk(KERN_DEBUG"Goodbye\n");
-
flush_scheduled_work();
-
}
-
module_init(demo_init);
-
module_exit(demo_exit);
6 执行结果
转载本文时请注明出自:
add358.blog.chinaunix.net
阅读(2862) | 评论(0) | 转发(0) |