您的位置:首页 > 其它

list_for_each与list_for_each_entry

2015-05-25 18:42 337 查看
分析的结果:

1.list_for_each和list_for_each_entry都是遍历链表的两个宏,本质上都是for循环。

2.他们做的事情本质上都一样,A.获取链表头,B.判断链表项是不是链表头,C.指向链表的下一项。

3.他们的区别:list_for_each遍历的链表,其链表项不属于某个结构体。或者说不关心它是不是包含在某个结构体中。

list_for_each_entry遍历的链表,其每一项都是某个结构体中的成员,单纯遍历链表还不行,还要找到包含这个

链表项的结构体的地址,从而为下一步应用该结构体做好准备。

/*******************************************************************************************************************************/

/***********************内核重要链表操作函数:list_for_each的源码分析***********************************************************/

/*******************************************************************************************************************************/

list_for_each内核中的定义:

/**

* list_for_each -
iterate over a list

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

* @head: the head for your list.

*/

#define list_for_each(pos, head) \

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

/*

*对list_for_each的理解:

*1.首先看内核中的注释:iterate over a list,翻译为中文就是遍历链表,@pos:
the &struct list_head to use as a loop cursor.翻译:

*结构体list_head使用的循环游标。@head: the head for your list.翻译:链表头

*2.看源码:#define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next)

*就是一个简单的for循环。循环的初始化工作:pos指向链表头的下一项。循环的条件:pos不是链表头。每次循环要做的事情:pos指向链表中的下一项

*3.总结。这个段代码还是很好理解的,list_for_each 会被替换为一个for循环,用于遍历一个链表。

*/

/*******************************************************************************************************************************/

/***********************内核重要链表操作函数:list_entry***的源码分析***********************************************************/

/*******************************************************************************************************************************/

list_entry内核源码:

/**

* list_entry - get the struct for this entry

* @ptr: the &struct list_head pointer.

* @type: the type of the struct this is embedded in.

* @member: the name of the list_struct within the struct.

*/

#define list_entry(ptr, type, member) \

container_of(ptr, type, member)

/*

*1.内核注释:list_entry - get the struct for this entry,翻译:获得这一项的结构体

*@ptr: the &struct list_head pointer.
翻译:

*2.从源码中看:list_entry就是container_of,因此搞懂container_of就搞懂了list_entry.看下面的container_of的解析

*/

/*******************************************************************************************************************************/

/***********************内核重要链表操作函数:container_of的源码分析************************************************************/

/*******************************************************************************************************************************/

container_of内核中的源码:

/**

* container_of - cast a member of a structure out to the containing structure

* @ptr: the pointer to the member.

* @type: the type of the container struct this is embedded in.

* @member: the name of the member within the struct.

*

*/

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({ \

const typeof(((type *)0)->member)*__mptr = (ptr); \

(type *)((char *)__mptr - offsetof(type, member)); })

/*

*1.内核中的注释:container_of - cast a member of a structure out to the containing structure,翻译:通过某个结构体成员计算出包含它的结构体

*@ptr: the pointer to the member.翻译:结构体成员指针

*@type: the type of the container struct this is embedded in,翻译:包含着给定成员的结构体的类型

*@member: the name of the member within the struct.翻译:给定成员的名字

*2.源码分析:#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

*这个宏,核心代码:((size_t) &((TYPE *)0)->MEMBER),这样理解:有个type*的结构体,地址为0,它指向member成员,

*此时member成员的地址就是member在结构体中的偏移。因此,这个宏叫offsetof,即...的偏移

*然后分析:

*#define container_of(ptr, type, member) ({ \

* const typeof(((type *)0)->member)*__mptr = (ptr); \

* (type *)((char *)__mptr - offsetof(type, member)); })

*这个宏的核心代码是:({const typeof(((type *)0)->member)*__mptr = (ptr);(type *)((char *)__mptr - offsetof(type, member));})这个代码块

*2.1第一句:const typeof(((type *)0)->member)*__mptr = (ptr),定义了__mptr指针,指针类型为 const typeof((type *)0)->member)

*typeof((type *)0)->member)就是获取member的类型,因此:第一句定义了一个和member类型一样的指针。并且指向了ptr

*2.2第二句:(type *)((char *)__mptr - offsetof(type, member))

*第一句理解了,第二句就很好理解了。__mptr的地址就是传入的ptr的地址。这个地址减去member在包含它的结构体中的偏移,不就是包含它的结构体的地址吗?

*因此,第二句的意思就是通过给定的结构体某个成员的地址,算出该成员在结构体中的偏移,然后用改地址减去该偏移,从而得到包含它的结构体的地址。

*/

/*******************************************************************************************************************************/

/***********************内核重要链表操作函数:list_for_each_entry的源码分析*****************************************************/

/*******************************************************************************************************************************/

list_for_each_entry在内核中的定义:

/**

* list_for_each_entry -
iterate over list of given type

* @pos: the type * to use as a loop cursor.

* @head: the head for your list.

* @member: the name of the list_struct within the struct.

*/

#define list_for_each_entry(pos, head, member)
\

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

&pos->member != (head);
\

pos = list_entry(pos->member.next, typeof(*pos), member))

/*

*1.首先看内核中的注释:遍历给定类型列表,这里就和list_for_each不同了,list_for_each是遍历一个链表。

*@pos: the type * to use as a loop cursor.翻译:作为循环游标的类型

*@head: the head for your list.
翻译:链表头

*@member: the name of the list_struct within the struct. 翻译:结构体中的链表结构体的名字

*2.看源码:也是一个for循环。

*2.1初始化工作:调用list_entry,list_entry就是container_of,container_of上面已经分析,就是通过成员地址计算出包含该成员的结构体地址

*因此,初始化工作,找到给定成员构造的链表中第一项的的接头体地址并赋值给pos.

*2.2循环执行的条件:链表项不是链表头

*2.3循环每次都要做的事情。pos指向给定链表下一项的被包含的结构体的地址。

*总结:list_for_each_entry也是用来遍历链表的,只不过这个链表有点特使,构成链表的每一项是更高一级结构体中的某一项

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