当前位置: 代码迷 >> 综合 >> linux2.6中的工作队列接口 workqueue_struct
  详细解决方案

linux2.6中的工作队列接口 workqueue_struct

热度:2   发布时间:2024-01-21 13:22:11.0
工作队列接口

  工作队列接口是在2.5的开发过程中引入的,用于取代任务队列接口(用于调度内核任务)。每个工作队列有一个专门的线程,所有来自运行队列的任 务在进程的上下文中运行(这样它们可以休眠)。驱动程序可以创建并使用它们自己的工作队列,或者使用内核的一个工作队列。工作队列用以下方式创建:

  struct workqueue_struct *create_workqueue(const char *name);
在这里 name 是工作队列的名字。

  工作队列任务可以在编译时或者运行时创建。任务需要封装为一个叫做 work_struct 的结构体。在编译期初始化一个工作队列任务时要用到:

  DECLARE_WORK(name, void (*function)(void *), void *data);
在这里 name 是 work_struct 的名字,function 是当任务被调度时调用的函数,data 是指向那个函数的指针。

  在运行期初始化一个工作队列时要用到:

  INIT_WORK(struct work_struct *work, void (*function)(void *), void *data);
用下面的函数调用来把一个作业(一个类型为work_struct 结构的工作队列作业/任务)加入到工作队列中:

  int queue_work(struct workqueue_struct *queue, struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *queue, struct work_struct
*work, unsigned long delay);

  在queue_delay_work()中指定 delay,是为了保证至少在经过一段给定的最小延迟时间以后,工作队列中的任务才可以真正执行。

  工作队列中的任务由相关的工作线程执行,可能是在一个无法预期的时间(取决于负载,中断等等),或者是在一段延迟以后。任何一个在工作队列中等待了无限长的时间也没有运行的任务可以用下面的方法取消:

  int cancel_delayed_work(struct work_struct *work);
如果当一个取消操作的调用返回时,任务正在执行中,那么这个任务将继续执行下去,但不会再加入到队列中。清空工作队列中的所有任务使用:

  void flush_workqueue(struct workqueue_struct *queue);
销毁工作队列使用:

  void destroy_workqueue(struct workqueue_struct *queue);
不是所有的驱动程序都必须有自己的工作队列。驱动程序可以使用内核提供的缺省工作队列。由于这个工作队列由很多驱动程序共享,任务可能会需要比较长一段时间才能开始执行。为了解决这一问题,工作函数中的延迟应该保持最小或者干脆不要。

  需要特别注意的是缺省队列对所有驱动程序来说都是可用的,但是只有经过GP许可的驱动程序可以用自定义的工作队列:

  int schedule_work(struct work_struct *work); -- 向工作队列中添加一个任务
int schedule_delayed_work(struct work_struct *work, unsigned long delay); -- 向工作队列中添加一个任务并延迟执行

  当模块被缷载时应该去调用一个 flash_scheduled_work() 函数,这个函数会使等待队列中所有的任务都被执行。