您的位置:首页 > 其它

工作队列的初始化(INIT_WORK的参…

2013-12-19 20:37 204 查看
在编写工作队列的小例子时,遇到

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

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

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

from http://blog.csdn.net/fudan_abc/archive/2007/08/20/1751565.aspx

于是就让我们来仔细看看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)

解决方法:

http://ubuntuforums.org/showthread.php?t=441180

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(不过没试过)

http://www.linuxsir.org/bbs/thread310620.html

=>
http://rt2x00.serialmonkey.com/phpBB/viewtopic.php?f=8&t=2951&start=0&st=0&sk=t&sd=a&sid=0681e465914045dedf06f35334b99131
==>

(about work_struct and INIT_WORK )

http://lwn.net/Articles/213149/

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);

...

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: