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.pswp.cn/bicheng/89561.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/89561.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分布式面试点

目录 1.分布式理论 为什么CAP不可兼得呢? 2.CAP对应的模型和应用 3.Base理论 4,有哪些分布式锁的案例 5.分布式事务 6.Seata 分布式一致性算法 1. 准备阶段(Prepare Phase) 2. 接受阶段(Accept Phase) 3. 学习阶段&…

Neo4j系列---【Linux离线安装neo4j】

Linux离线安装neo4j 1.官方安装文档 地址:https://neo4j.com/docs/operations-manual/current/installation/linux/tarball/ 2.如果浏览器无法访问 修改neo4j.conf,开放所有ip访问 # 允许所有IP地址访问 server.default_listen_address0.0.0.0 3.创建开机自启动服务…

SEO长尾关键词核心实战技巧提升排名

内容概要 本文聚焦于SEO长尾关键词的核心实战技巧,旨在帮助读者精准锁定目标用户的搜索意图,从而提升网站自然排名和获取精准流量。文章将从基础概念入手,系统解析如何挖掘高转化率的长尾关键词,优化内容结构以增强搜索可见度&…

当OT遇见IT:Apache IoTDB如何用“时序空间一体化“技术破解工业物联网数据孤岛困局?

目录 一. 什么是时序数据库? 二. 时序数据库的选型要素 性能指标 架构能力 数据模型与查询能力 安全与权限控制 部署与运维能力 三 Apache IoTDB 简介及安装使用: 安装准备教程 检查 Java 版本 下载与安装 下载 IoTDB 解压文件 配置环境变量 启动…

一文讲透HTML语义化标签

文章目录语义化标签概述HTML标签及其含义常见HTML5语义化标签语义化标签对搜索引擎(SEO)的影响提升搜索引擎排名增强可访问性改善用户体验语义化标签案例各标签作用说明语义化标签概述 HTML 语义化是指使用恰当的标签来准确表达内容的结构和含义&#x…

Django 实战:静态文件与媒体文件从开发配置到生产部署

文章目录一、静态文件与媒体文件区别与联系配置开发环境配置二、媒体文件实战实战场景定义模型定义序列化器定义视图实战效果三、生产部署说明收集静态文件Nginx配置示例OpenResty配置示例一、静态文件与媒体文件 区别与联系 在 Django 项目中,静态文件&#xff0…

Python自动化分析知网文献:爬取、存储与可视化

1. 引言 在当今的学术研究和大数据分析领域,高效获取和分析学术文献数据具有重要意义。中国知网(CNKI)作为国内最权威的学术资源平台之一,包含了海量的期刊论文、会议论文和学位论文。然而,手动收集和分析这些数据不仅…

Python应用指南:使用PyKrige包实现ArcGIS的克里金插值法

先了解什么是克里金插值?克里金插值(Kriging interpolation)是一种基于统计学和空间相关性的高级空间插值方法,广泛应用于地理信息系统(GIS)、地质勘探、环境科学、气象学等领域。它由南非矿业工程师丹尼尔…

Redis原理之哨兵机制(Sentinel)

上篇文章: Redis原理之主从复制https://blog.csdn.net/sniper_fandc/article/details/149141103?fromshareblogdetail&sharetypeblogdetail&sharerId149141103&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 目录 1 哨兵机制恢…

uniapp打包成 apk

1. 先把项目打包成 index.html 上传到宝塔服务器,关联到域名 2.然后再用hbuilder新建一个 基础模板的 uniapp 3.再修改代码,采用iframe方式打包 pages/index/index <template><web-view v-if="showWebView" :src="webViewSrc" @message=&qu…

RPG57.创建玩家拾取物品类一:创建可拾取物品类的基类

1。新建一个基类&#xff0c;用于玩家可拾取物品的父类然后// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "Components/SphereComponent.h" #include "GameFramewo…

k8s之持久化存储流程

K8s 中的 Pod 在挂载存储卷时需经历三个的阶段&#xff1a;Provision/Delete&#xff08;创盘/删盘&#xff09;、Attach/Detach&#xff08;挂接/摘除&#xff09;和 Mount/Unmount&#xff08;挂载/卸载&#xff09; Provisioning Volumes 时序流程详解 一、流程图 sequenc…

python学智能算法(二十四)|SVM-最优化几何距离的理解

引言 前序学习过程中&#xff0c;已经对几何距离的概念有了认知&#xff0c;学习链接为&#xff1a;几何距离 这里先来回忆几何距离δ的定义&#xff1a; δmin⁡i1...myi(w∥w∥⋅xib∥w∥)\delta \min_{i1...m}y_{i}(\frac{w}{\left \| w \right \|}\cdot x_{i}\frac{b}{\le…

创建游戏或互动体验:从概念到实现的完整指南

Hi&#xff0c;我是布兰妮甜 &#xff01;在数字时代&#xff0c;游戏和互动体验已成为娱乐、教育和商业领域的重要组成部分。本文将带你了解如何使用JavaScript创建引人入胜的游戏和互动体验&#xff0c;从基础概念到实际实现。 文章目录一、游戏开发基础1.1 游戏循环1.2 游戏…

SpringMVC + Tomcat10

1. Tomcat 10的servlet包路径变了&#xff0c;javax -> jakarta 2. DispatcherServlet从Spring6 才开始使用jakarta.servlet.http.Servlet 3. Spring6 需要JDK 17 1. pom <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org…

Django `transaction.atomic()` 完整使用指南

目录 #概述#基本用法#事务一致性保障机制#破坏一致性的常见场景#高级用法#最佳实践#诊断与调试#附录 概述 transaction.atomic() 是 Django 提供的数据库事务管理工具&#xff0c;用于确保一系列数据库操作要么全部成功提交&#xff0c;要么全部回滚&#xff0c;维护数据的一致…

UDP协议的端口161怎么检测连通性

UDP 端口 161 (SNMP) 连通性检测的专业指南 UDP 161 端口是 SNMP (Simple Network Management Protocol) 服务的标准端口。由于其无连接特性&#xff0c;检测需要特殊方法。以下是全面的检测方案&#xff1a; 一、专业检测方法 1. 使用 SNMP 专用工具&#xff08;推荐&#xff…

进阶数据结构:红黑树

嘿&#xff0c;各位技术潮人&#xff01;好久不见甚是想念。生活就像一场奇妙冒险&#xff0c;而编程就是那把超酷的万能钥匙。此刻&#xff0c;阳光洒在键盘上&#xff0c;灵感在指尖跳跃&#xff0c;让我们抛开一切束缚&#xff0c;给平淡日子加点料&#xff0c;注入满满的pa…

如何上传github(解决git的时候输入正确的账号密码,但提示认证失败)

如何上传github文件&#xff0c;删除文件 1.重点 GitHub 从 2021 年 8 月 13 日起移除了对密码认证的支持。你需要使用个人访问令牌(Personal Access Token, PAT)或 SSH 密钥来进行认证。 2.生成SSH key 进入设置点击New SSH Key名字随便取&#xff0c;可以自己方便记3.上传文件…

多级缓存架构与热点探测系统核心技术解析

多级缓存架构与热点探测系统核心技术解析 &#x1f4cc; 一、多级缓存架构 1. 为什么需要多级缓存&#xff1f; ✅ 本地缓存优势&#xff1a; &#x1f680; 减少网络请求&#xff0c;提升访问性能&#x1f310; 分布式系统中天然具有分布式缓存特性⬇️ 有效降低远程缓存&…