找回密码
 注册
搜索
热搜: 回贴
微赢网络技术论坛 门户 服务器 Linux/BSD 查看内容

内核链表2

2009-12-20 13:34| 发布者: admin| 查看: 58| 评论: 0|原作者: 玄霄








遍历:
这部分代码比较长,不过有些还是比较相似的,所以不用担心,我们来一步一步往下看。

425#define
list_entry
(
ptr
,
type
,
member
)
\

426

container_of
(
ptr
,
type
,
member
)

427
List_entry()这个宏又牵扯到一个宏container_of(),有必要把这个宏详细分析下,这个宏用途很广,说明其也很重要。
//在头文件include/linux/kernel.h中有此定义。

318#define

container_of
(
ptr
,

type
,

member
)
({ \

319
const
typeof
(
((
type

*)0)->
member

) *
__mptr

= (
ptr
);
\

320
(
type

*)( (char *)
__mptr

-
offsetof
(
type
,
member
)
);})
他的作用是:通过结构中的某个变量获取结构本身的指针。
typeof()和offsetof(),它们返回的是某个变量的类型和结构中某变量在结构中的偏移量。typeof()是gcc的扩展。
offsetof宏定义在[include/linux/stddef.h]中:
#define
offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
offsetof宏的实现非常巧妙,它把0地址转化为TYPE结构的指针,然后获取该结构中MEMBER成员的指针,并将其强制类型转换为
size_t类型。于是,由于结构从0地址开始定义,因此,强制转换后的MEMBER成员地址,实际上就是它在结构中的偏移量,这也显示出了C语言中指针的强大。
看下面的图六可以帮助理解。ptr是指向结构体type类型中的一个成员(member)的指针,这样三个参数我们都知道了,第319行_mptr强制转换成ptr所指向的类型,然后把ptr赋给它。320行_mptr减去member在type中的偏移量(由offsetof(type,member)算出),这样就等于将ptr指针向后移动了offsetof()个偏移量,即就是指针指向了type指向的位置。一般使用时member成员为struct
list_head结构(注意这个,这就是这个宏的妙用,在后面的文章中将会举个例子说明它的妙处)。
screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL Mouse wheel to zoom in/out';}" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open('http://blogimg.chinaunix.net/blog/upfile2/081012201010.jpg');}" onmousewheel="return imgzoom(this);" alt="" />
综上述可知list_entry()可以得到一个type类型的结构体。

436#define
list_first_entry
(
ptr
,
type
,
member
)
\

437

list_entry
((
ptr
)->
next
,
type
,
member
)
知道了list_entry()的用法,list_first_entry()就无需多言了吧。

444#define
list_for_each
(
pos
,
head
)
\

445
for (
pos
= (
head
)->
next
;
prefetch
(
pos
->
next
),
pos
!= (
head
);
\

446

pos
=
pos
->
next
)

447
此函数作用:循环访问一个链表。遍历访问是这样进行的:head是链表头,从head->next开始,一直到pos指向最后一个项即就是head->prev为止,函数prefetch()是预先取得下一个链表项,为了加快速度。

458#define
__list_for_each
(
pos
,
head
)
\

459
for (
pos
= (
head
)->
next
;
pos
!= (
head
);
pos
=
pos
->
next
)

460
这个宏和list_for_each()类似,不同之处在于,这个没有预取函数prefetch(),一般是短链表才使用这个宏。

461/**

462
* list_for_each_prev - iterate over a list backwards

463
* @pos: the &struct list_head to use as a loop cursor.

464
* @head: the head for your list.

465
*/

466#define
list_for_each_prev
(
pos
,
head
)
\

467
for (
pos
= (
head
)->
prev
;
prefetch
(
pos
->
prev
),
pos
!= (
head
);
\

468

pos
=
pos
->
prev
)

469
此宏和list_for_each()相反,沿着相反的方向(head->prev)遍历,最后是pos指向了head->next。

476#define
list_for_each_safe
(
pos
,
n
,
head
)
\

477
for (
pos
= (
head
)->
next
,
n
=
pos
->
next
;
pos
!= (
head
);
\

478

pos
=
n
,
n
=
pos
->
next
)

479
这个宏是list_for_each()的“安全版”,它先将pos的下一个即pos->next赋给n,然后pos=n;防止了pos->next在未赋值给pos前被移除造成的链表断裂。

486#define
list_for_each_entry
(
pos
,
head
,
member
)
\

487
for (
pos
=
list_entry
((
head
)->
next
,
typeof
(*
pos
),
member
);
\

488

prefetch
(
pos
->
member
.
next
),
&
pos
->
member
!= (
head
);
\

489

pos
=
list_entry
(
pos
->
member
.
next
,
typeof
(*
pos
),
member
))
遍历一个给定链表,member为链表项中的成员,为struct
head_list型,head为链表头,最后将指向链表的最后一项。

497#define
list_for_each_entry_reverse
(
pos
,
head
,
member
)
\

498
for (
pos
=
list_entry
((
head
)->
prev
,
typeof
(*
pos
),
member
);
\

499

prefetch
(
pos
->
member
.
prev
),
&
pos
->
member
!= (
head
);
\

500

pos
=
list_entry
(
pos
->
member
.
prev
,
typeof
(*
pos
),
member
))
与list_for_each_entry()类似,只不过是反向遍历而已。







最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-30 13:32 , Processed in 0.153657 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

返回顶部