list_for_each与list_for_each_entry

分析的结果:
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也是用来遍历链表的,只不过这个链表有点特使,构成链表的每一项是更高一级结构体中的某一项
*/



  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值