您现在的位置:主页 > 技术中心 > 操作系统 > Linux

Linux中的工作队列

来源:网络 责任编辑:admin 发表时间:2013-07-01 21:16 点击:

[前记]Linux自从2.6.20之后,工作队列发生了一些变化,目前从网络上搜索的资料一般都是介绍老版本的工作队列,很少见到对新版本的介绍。本文对新老版本都做了简要概述,并分别提供了简单的实作案例。


*******************************************************************************************************************

工作队列(work queue)是Linux kernel中将工作推后执行的一种机制。这种机制和BH或Tasklets不同之处在于工作队列是把推后的工作交由一个内核线程去执行,因此工作队列的优势就在于它允许重新调度甚至睡眠。
工作队列是2.6内核开始引入的机制,在2.6.20之后,工作队列的数据结构发生了一些变化,因此本文分成两个部分对2.6.20之前和之后的版本分别做介绍。
1、2.6.0~2.6.19
数据结构:
struct work_struct {
    unsigned long pending;
    struct list_head entry;
    void (*func)(void *);
    void *data;
    void *wq_data;
    struct timer_list timer;
};
pending是用来记录工作是否已经挂在队列上;
entry是循环链表结构;
func作为函数指针,由用户实现;
data用来存储用户的私人数据,此数据即是func的参数;
wq_data一般用来指向工作者线程(工作者线程参考下文);
timer是推后执行的定时器。
work_struct的这些变量里,func和data是用户使用的,其他是内部变量,我们可以不用太过关心。
 
API:
1) INIT_WORK(_work, _func, _data)
初始化指定工作,目的是把用户指定的函数_func及_func需要的参数_data赋给work_struct的func及data变量。
2) int schedule_work(struct work_struct *work)
对工作进行调度,即把给定工作的处理函数提交给缺省的工作队列和工作者线程。工作者线程本质上是一个普通的内核线程,在默认情况下,每个CPU均有一个类型为“events”的工作者线程,当调用schedule_work时,这个工作者线程会被唤醒去执行工作链表上的所有工作。
3) int schedule_delayed_work(struct work_struct *work, unsigned long delay)
延迟执行工作,与schedule_work类似。
4) void flush_scheduled_work(void)
刷新缺省工作队列。此函数会一直等待,直到队列中的所有工作都被执行。
5) int cancel_delayed_work(struct work_struct *work)
flush_scheduled_work并不取消任何延迟执行的工作,因此,如果要取消延迟工作,应该调用cancel_delayed_work。
 
以上均是采用缺省工作者线程来实现工作队列,其优点是简单易用,缺点是如果缺省工作队列负载太重,执行效率会很低,这就需要我们创建自己的工作者线程和工作队列。
API:
1) struct workqueue_struct *create_workqueue(const char *name)
创建新的工作队列和相应的工作者线程,name用于该内核线程的命名。
2) int queue_work(struct workqueue_struct *wq, struct work_struct *work)
类似于schedule_work,区别在于queue_work把给定工作提交给创建的工作队列wq而不是缺省队列。
3) int queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay)
延迟执行工作。
4) void flush_workqueue(struct workqueue_struct *wq)
刷新指定工作队列。
5) void destroy_workqueue(struct workqueue_struct *wq)
释放创建的工作队列。
 
下面一段代码可以看作一个简单的实作:
 
void my_func(void *data)
{
    char *name = (char *)data;
    printk(KERN_INFO “Hello world, my name is %s!\n”, name);
}
 
struct workqueue_struct *my_wq = create_workqueue(“my wq”);
struct work_struct my_work;
 
INIT_WORK(&my_work, my_func, “Jack”);
queue_work(my_wq, &my_work);
 
destroy_workqueue(my_wq);
 
 
2、2.6.20~2.6.??
自2.6.20起,工作队列的数据结构发生了一些变化,使用时不能沿用旧的方法。
 
数据结构:
typedef void (*work_func_t)(struct work_struct *work);
struct work_struct {
    atomic_long_t data;
    struct list_head entry;
    work_func_t func;
};
 
与2.6.19之前

    相关新闻>>

      发表评论
      请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
      评价:
      表情:
      用户名: 验证码:点击我更换图片

      推荐热点

      • /etc/fstab 详解
      • nginx主主集群
      •  LVS-NAT和LVS-DR模式的实现详解
      •  RHCE考试之磁盘配额
      • 学习笔记:ACL详解
      •  LVM逻辑卷管理器
      • suse linux双网卡双网关配置
      •  Nginx主主负载均衡架构
      • linux top命令详解

      快速直达

      ?? - ?? - ÝřŝžľŘÝź - TAGąęÇŠ - RSSśŠÔÄ - ??
      Copyright © 2004-2024 上海卓卓网络科技有限公司