list初始化_Linux内核中container_of 和list_for_each_entry有什么区别?

container_of

功能:根据结构体中成员的地址从而获取到这个成员所在的结构体的首地址。

0a1f60bf4e1055af5da5ca5bab7b24d2.png

首先可以看出container_of被预定义成一个函数,三个参数,ptr:已知的结构体的成员的地址;type:结构体的类型;member:结构体成员的名字;函数的第一句代码,通过((type *)0)->member定义一个MEMBER型的指针__mptr,这个指针指向ptr参数,所以第一段代码获取到了结构体的成员member的地址;接下来我们用这个地址减去结构体成员member在结构体中的相对偏移量,就可以获取到所求结构体的首地址:(char *)__mptr - offsetof(type,member)就实现了这个过程,最后再把这个地址强制转换成type型指针,就获取到了所求结构体指针,define预定义返回最后一句话的值,将所求结构体指针返回。所以整个container_of的功能就是通过指向结构体成员member的指针ptr获取指向整个结构体的指针。container_of清楚了,那list_entry就更是一目了然了。

aca82c90092178c11243bc933b1a52e0.png

list_entry的功能等同于container_of。接下来分析list_for_each_entry的实现过程。

list_for_each_entry

Linux内核代码中,要经常对链表进行操作,list_for_each_entry是操作链表非常重要的一个宏函数:遍历给定类型的链表。

4ae1a2f6d117b55a2aa0f4c83407e698.png

在理解了list_entry的基础上分析list_for_each_entry是一件比较轻松的事情,但在这里还是要强调一下双向链表及链表头的概念,否则对list_for_each_entry的理解还是一知半解。建立一个双向链表通常有一个独立的用于管理链表的链表头,链表头一般是不含有实体数据的,必须用INIT_LIST_HEAD()进行初始化,表头建立以后,就可以将带有数据结构的实体链表成员加入到链表中。list_for_each_entry被预定义成一个for循环语句,for循环的第一句话获取(head)->next指向的member成员的数据结构指针,也就是将pos初始化为除链表头之外的第一个实体链表成员,for的第三句话通过pos->member.next指针遍历整个实体链表,当pos->member.next再次指向我们的链表头的时候跳出for循环。整个过程没有对链表头进行遍历(不需要被遍历),所以使用list_for_each_entry遍历链表必须从链表头开始。因此可以看出,list_for_each_entry的功能就是遍历以head为链表头的实体链表,对实体链表中的数据结构进行处理。

e25878a9352b2a909c97a49567ee5496.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值