当前位置: 首页 > news >正文

linux 的list_for_each_entry

linux的宏定义提高了代码的简洁性,但有时候的命名不够完美。比如list_for_each_entry,看名字只知道是遍历list,但一看里面的三个变量参数,有点懵逼。

/**
* 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_head within the struct.
*/
#define list_for_each_entry(pos, head, member)                          \
for (pos = list_first_entry(head, typeof(*pos), member);        \
!list_entry_is_head(pos, head, member);                    \
pos = list_next_entry(pos, member))
谁是given type? 被遍历的是谁?咋看看不出来。

/**
* list_first_entry - get the first element from a list
* @ptr:        the list head to take the element from.
* @type:       the type of the struct this is embedded in.
* @member:     the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/

#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)

这个宏的comments解释说是获取一个list的第一个元素。 但是一看宏定义有点懵,怎么又来一个宏在里面?

/**
* 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_head within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)

这个宏定义看解释是获取当前entry的所属结构体,又来一个宏:

  1. /**

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

  3. * @ptr: the pointer to the member.

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

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

  6. *

  7. * WARNING: any const qualifier of @ptr is lost.

  8. */

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

  10. void *__mptr = (void *)(ptr); \

  11. static_assert(__same_type(*(ptr), ((type *)0)->member) || \

  12. __same_type(*(ptr), void), \

  13. "pointer type mismatch in container_of()"); \

  14. ((type *)(__mptr - offsetof(type, member))); })

 此宏就是,给了一个结构体变量的其中成员变量,而获取此结构体变量的地址。ptr是成员变量地址,type是结构体类型,member是成员变量在结构体声明里的名字称谓。

所以说 list_entry 是获取ptr所属的结构体地址。list_first_entry 是获取(ptr)->next 所在结构体的地址,

而list_for_each_entry里面还有宏:

/**
* list_entry_is_head - test if the entry points to the head of the list
* @pos:        the type * to cursor
* @head:       the head for your list.
* @member:     the name of the list_head within the struct.
*/
#define list_entry_is_head(pos, head, member)                           \
(&pos->member == (head))
这个宏名字取的更敷衍。解释内容说是为了验证是不是list的头指针。 看代码是验证pos这个结构体的成员member地址是不是和head一样。

再看另外一个宏:

/**
* list_next_entry - get the next element in list
* @pos:        the type * to cursor
* @member:     the name of the list_head within the struct.
*/
#define list_next_entry(pos, member) \
list_entry((pos)->member.next, typeof(*(pos)), member)
解释内容说是获取list的下一个成员指针,看代码是获取(pos)->member.next 所在结构体的地址。

这样整体来看:

#define list_for_each_entry(pos, head, member)                          \
for (pos = list_first_entry(head, typeof(*pos), member);        \ //获取head->next所在结构体地址给pos
!list_entry_is_head(pos, head, member);                    \//判断pos的member成员地址是否和head一样,如果一样,就跳出循环
pos = list_next_entry(pos, member))   //获取(pos)->member.next 所在结构体的地址

综上所述,这里遍历了一个循环链表,表头是head,但是似乎head没被拿来遍历到?直接从head->next开始的?遍历到再次碰到head的地址就结束了,即表明遍历了一圈了。 member就是链表个成员(链表类型地址)内含的内容地址。这里head为什么是废弃的?

http://www.lryc.cn/news/592383.html

相关文章:

  • 五分钟掌握 TDengine 数据文件的工作原理
  • 【Unity】IEnumeratorCoroutine
  • 【面试题】大厂高压面经实录丨第二期
  • 解锁 Java 并发编程的奥秘:《Java 并发编程之美》中的技术亮点与难题攻克
  • 构建直播平台大体的流程
  • Netty封装Websocket并实现动态路由
  • 在git中同时配置gitcode和github访问权限
  • 微信小程序 wx.request() 的封装
  • 【图像处理基石】什么是CCM?
  • 解决 Selenium 页面跳转过快导致的内容获取问题:从原理到实践
  • 填坑 | React Context原理
  • 29、鸿蒙Harmony Next开发:深浅色适配和应用主题换肤
  • 私有服务器AI智能体搭建配置选择记录
  • 苍穹外卖项目日记(day12)
  • 再探Java多线程Ⅱ --- (创建方式+等待唤醒+Lock锁)
  • 【论文蒸馏】Recent Advances in Speech Language Models: A Survey
  • 《设计模式之禅》笔记摘录 - 8.命令模式
  • 企业如何让内部视频仅限公司官网或指定域名播放?
  • 2025年SEVC SCI2区,利用增强粒子群算法(MR-MPSO)优化MapReduce效率和降低复杂性,深度解析+性能实测
  • 某邮生活旋转验证码逆向
  • 5W8-3D牢游戏超级大集合[2012年6月] 地址 + 解压密码
  • Python绘制数据(二)
  • C语言实战:超级玛丽游戏
  • 工业数据集成中间件工具OPC Router详细介绍
  • 大模型格式
  • sky-take-out项目Mybatis的使用
  • AE电源MDX 5K 10K 15K 20K 25K 30K手侧操作使用说明
  • 【Linux】环境基础与开发工具的使用
  • 数据结构--JDK17新增语法和顺序表
  • blender如何队列渲染多个工程文件的动画?