博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
工作队列的初始化(INIT_WORK的参…
阅读量:4052 次
发布时间:2019-05-25

本文共 5625 字,大约阅读时间需要 18 分钟。

在编写工作队列的小例子时,遇到

error: macro "INIT_WORK" passed 3 arguments, but takes just 2

 

从2.6.20的内核开始,INIT_WORK宏做了改变,

原来是三个参数,后来改成了两个参数

 

 

from 

于是就让我们来仔细看看INIT_WORK和INIT_DELAYED_WORK.其实前者是后者的一个特例,它们涉及到的就是传说中的工作队列.这两个宏都定义于include/linux/workqueue.h中:

     79 #define INIT_WORK(_work, _func)                                         /

     80         do {                                                            /

     81                 (_work)->data = (atomic_long_t) WORK_DATA_INIT();       /

     82                 INIT_LIST_HEAD(&(_work)->entry);                        /

     83                 PREPARE_WORK((_work), (_func));                         /

     84         } while (0)

     85

     86 #define INIT_DELAYED_WORK(_work, _func)                         /

     87         do {                                                    /

     88                 INIT_WORK(&(_work)->work, (_func));             /

     89                 init_timer(&(_work)->timer);                    /

     90         } while (0)

 

解决方法:

Change the following lines:

static void ppsc_tq_int (void *data) 
change to 
static void ppsc_tq_int (struct work_struct *data)
INIT_WORK (&pha->wq, ppsc_tq_int, pha);
change to
INIT_WORK (&pha->wq, ppsc_tq_int);

成功!

 

另一个解决方法:container_of(不过没试过)

 

=>

==>

 (about work_struct and INIT_WORK )

 

 Okay.

(1) Any work_struct struct that has one of the following called upon it:
queue_delayed_work()
queue_delayed_work_on()
schedule_delayed_work()
schedule_delayed_work_on()
cancel_rearming_delayed_work()
cancel_rearming_delayed_workqueue()
cancel_delayed_work()
     needs changing into a delayed_work struct.
     Note that cancel_delayed_work() is often called where it'll be ineffective
     - I think people misunderstand what it does.
(2) A delayed_work struct must be initialised with:
__DELAYED_WORK_INITIALIZER
DECLARE_DELAYED_WORK
INIT_DELAYED_WORK
     Rather than:
__WORK_INITIALIZER
DECLARE_WORK
INIT_WORK
     Those only apply to work_struct (non-delayable work).
(3) The initialisation functions no longer take a data argument, and this
     should be deleted.
(4) Anywhere one of the following is called on a delayed_work struct:
queue_work()
queue_work_on()
schedule_work()
schedule_work_on()
     it must be converted to the equivalent one of:
queue_delayed_work()
queue_delayed_work_on()
schedule_delayed_work()
schedule_delayed_work_on()
     and given a 0 timeout argument as an additional argument.  This just
     queues the work item and doesn't set the timer.
(5) Anywhere the work item's pending flag is examined directly with:
test_bit(0, &work->pending)
     This should be replaced with the appropriate one of:
work_pending(work)
delayed_work_pending(work)
(6) The work function _must_ be changed to conform to the following prototype:
void foo_work_func(struct work_struct *work)
{
...
}
     This applies to both work_struct and delayed_work handlers.
     (a) If the arbitary datum previously passed to the initialiser was NULL,
     then the work argument should just be ignored.
     (b) If the datum was the address of the structure containing the
     work_struct, then something like the following should be used:
struct foo {
struct work_struct worker;
...
};
void foo_work_func(struct work_struct *work)
{
struct foo *foo = container_of(work, struct foo, worker);
...
}
If the work_struct can be placed at the beginning of the containing
structure this will eliminate the subtraction instruction
container_of() might otherwise require.
     (c) If the datum was the address of the structure containing the
     delayed_work, then something like the following should be used:
struct foo {
struct delayed_work worker;
...
};
void foo_work_func(struct work_struct *work)
{
struct foo *foo = container_of(work, struct foo, worker.work);
...
}
NOTE!  There's an extra ".work" in the container_of() because the
work_struct pointed to is embedded within the delayed_work.
     (d) If the datum is not a pointer to the container, but the container is
     guaranteed to exist whilst the work handler runs, then the datum can
     be stored in an extra variable in the container.
The handler would then be formed as for (b) or (c), and the extra
variable accessed after the container_of() line.
Quite often there's a linked pair of structures, with a work_struct in
one being initialised with the address of the other as its datum.  The
typical case is struct net_device and the private data.  In this case
just adding a back pointer from the private data to the net_device
struct seems to work.
     (e) If the auxiliary datum is totally unrelated and can't be stored in an
     extra variable because the container might go away, then the
     work_struct or delayed_work should be initialised with one of these
     instead:
DECLARE_WORK_NAR
DECLARE_DELAYED_WORK_NAR
INIT_WORK_NAR
INIT_DELAYED_WORK_NAR
__WORK_INITIALIZER_NAR
__DELAYED_WORK_INITIALIZER_NAR
These take the same arguments as the normal initialisers, but set a
flag in the work_struct to indicate that the pending flag is not to be
cleared before the work function is called.
The datum is then stored in an extra variable in the container:
struct foo {
struct work_struct worker;
void *worker_data;
...
};
And a work item is initialised with something like this:
void thing(struct foo *foo)
{
...
INIT_WORK_NAR(&foo->worker, foo_work_func);
foo->worker_data = silly_data;
...
}
And then the work function releases the work item itself when it has
extracted the auxiliary data:
void foo_work_func(struct work_struct *work)
{
struct foo *foo = container_of(work, struct foo, worker);
void *silly_data = foo->worker_data;
work_release(work);
...
}
As an added bonus, you can have multiple auxiliary data if you so
desire.  You're not limited to a single word.
(7) If the work function was being called directly, then rather than passing
     in the auxiliary datum, you have to pass in the address of the work_struct
     instead.  So for a work_struct, you'd change:
void call_work(struct foo *foo)
{
...
- foo_work_func(foo);
+ foo_work_func(&foo->worker);
...
}
     And for a delayed_work, you'd do:
void call_work(struct foo *foo)
{
...
- foo_work_func(foo);
+ foo_work_func(&foo->worker.work);
...
}

转载地址:http://kzpci.baihongyu.com/

你可能感兴趣的文章
jxbrowser 实现自定义右键菜单 jxbrowser破解版请联系作者
查看>>
快速开发框架设计
查看>>
需要统计的数据
查看>>
eclipse js jsp 卡怎么办,解决办法
查看>>
高性能J2EE接口平台设计
查看>>
spring mvc tomcat 线程池的坑
查看>>
JAVA 生成不重复订单号 优化版本 订单号格式为yyyymmdd后面自增
查看>>
mybatis-jpa插件使用教程
查看>>
cas 4.2.7 和 Nginx 整合遇到的问题 登录一会可以一会不可以
查看>>
CAS 单点登出 loginout 解决方案 -- 最靠谱的方案,不是抄的--还是不靠谱大家不要抄了
查看>>
springboot 支持jsp 直接访问jsp办法无需通过controller转发
查看>>
后续框架可以优化的点
查看>>
SpringBoot Logback 配置参数迁移到配置中心 Apollo
查看>>
springboot 自定义webroot的目录
查看>>
springboot springmvc j2ee 做伪静态化 .html 转发到 .jsp
查看>>
我入行以来java框架的几个阶段&论什么是真正的组件开发&项目中部分源码干货分享
查看>>
java-真正面向配置+组件的开发
查看>>
Mybattis Jpa插件简介
查看>>
java编程奇淫技巧之让java帮我们生成java代码后不停服,直接编译为class并且反射为对象直接使用
查看>>
springMVC源码阅读之FORM参数绑定
查看>>