分类: LINUX
2008-10-12 20:10:17
遍历:
这部分代码比较长,不过有些还是比较相似的,所以不用担心,我们来一步一步往下看。
#define (, , ) \
(, , )
List_entry()这个宏又牵扯到一个宏container_of(),有必要把这个宏详细分析下,这个宏用途很广,说明其也很重要。
//在头文件include/linux/kernel.h中有此定义。
#define (, , ) ({ \
const ( (( *)0)-> ) * = (); \
( *)( (char *) - (,) );})
他的作用是:通过结构中的某个变量获取结构本身的指针。
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结构(注意这个,这就是这个宏的妙用,在后面的文章中将会举个例子说明它的妙处)。
综上述可知list_entry()可以得到一个type类型的结构体。
#define (, , ) \
(()->, , )
知道了list_entry()的用法,list_first_entry()就无需多言了吧。
#define (, ) \
for ( = ()->; (->), != (); \
= ->)
此函数作用:循环访问一个链表。遍历访问是这样进行的:head是链表头,从head->next开始,一直到pos指向最后一个项即就是head->prev为止,函数prefetch()是预先取得下一个链表项,为了加快速度。
#define (, ) \
for ( = ()->; != (); = ->)
这个宏和list_for_each()类似,不同之处在于,这个没有预取函数prefetch(),一般是短链表才使用这个宏。
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define (, ) \
for ( = ()->; (->), != (); \
= ->)
此宏和list_for_each()相反,沿着相反的方向(head->prev)遍历,最后是pos指向了head->next。
#define (, , ) \
for ( = ()->, = ->; != (); \
= , = ->)
这个宏是list_for_each()的“安全版”,它先将pos的下一个即pos->next赋给n,然后pos=n;防止了pos->next在未赋值给pos前被移除造成的链表断裂。
#define (, , ) \
for ( = (()->, (*), ); \
(->.), &-> != (); \
= (->., (*), ))
遍历一个给定链表,member为链表项中的成员,为struct head_list型,head为链表头,最后将指向链表的最后一项。
#define (, , ) \
for ( = (()->, (*), ); \
(->.), &-> != (); \
= (->., (*), ))
与list_for_each_entry()类似,只不过是反向遍历而已。