linux内核——list_for_each_entry

2023-11-03

在Linux内核源码中,经常要对链表进行操作,其中一个很重要的宏是list_for_each_entry:
意思大体如下:
假设只有两个结点,则第一个member代表head,
list_for_each_entry的作用就是循环遍历每一个pos中的member子项。

 

宏list_for_each_entry:

 

  1.    /** 
  2. 401 * list_for_each_entry  -       iterate over list of given type 
  3. 402 * @pos:        the type * to use as a loop cursor. 
  4. 403 * @head:       the head for your list. 
  5. 404 * @member:     the name of the list_struct within the struct. 
  6. 405 */  
  7. 406#define list_for_each_entry(pos, head, member)                          /  
  8. 407        for (pos = list_entry((head)->next, typeof(*pos), member);      /  
  9. 408             prefetch(pos->member.next), &pos->member != (head);        /  
  10. 409             pos = list_entry(pos->member.next, typeof(*pos), member))  
 

 

list_entry((head)->next, typeof(*pos), member)返回(head)->next物理指针所处位置向前减去offsetof()个字节数据之后, 其父变量pos的物理地址,父变量的类型在编译时由typeof(*pos)自动返回.
所以list_for_each_entry遍历head下面挂接的类型为typeof(*pos)的childs结构体们,当然每个child结构体包含struct list_head node之类相似的双向链表list_head类型项,就这样通过循环pos将依次指向双向链表上的各个child.(member就是child类型中被定义的变量名)

其中用到了函数list_entry():
这个函数的作用在图1中表示就是可以通过已知的指向member子项的指针,获得整个结构体的指针(地址)

 

  1. /** 
  2. 329 * list_entry - get the struct for this entry 
  3. 330 * @ptr:        the &struct list_head pointer. 
  4. 331 * @type:       the type of the struct this is embedded in. 
  5. 332 * @member:     the name of the list_struct within the struct. 
  6. 333 */  
  7. 334#define list_entry(ptr, type, member) /  
  8. 335        container_of(ptr, type, member)  
 

 

和函数prefetch:

其中用到了builtin_prefetch:
prefetch的含义是告诉cpu那些元素有可能马上就要用到,告诉cpu预取一下,这样可以提高速度
其中用到了函数container_of():

 

  1. /** 
  2. 487 * container_of - cast a member of a structure out to the containing structure 
  3. 488 * @ptr:        the pointer to the member. 
  4. 489 * @type:       the type of the container struct this is embedded in. 
  5. 490 * @member:     the name of the member within the struct. 
  6. 491 * 
  7. 492 */  
  8. 493#define container_of(ptr, type, member) ({                      /  
  9. 494        const typeof( ((type *)0)->member ) *__mptr = (ptr);    /  
  10. 495        (type *)( (char *)__mptr - offsetof(type,member) );})  
 

 

下面这个链接讲container_of的作用,很详细了:
http://blog.chinaunix.net/u1/58968/showart_461749.html

再附一个很好的测试container_of作用的链接:
http://hi.baidu.com/xiquanlian/blog/item/a070d658642ea482810a18e3.html

其中又用到了offsetof()函数:
lxr上找到的源码:

 

  1. #define offset_of(type, memb) /  
  2.   47        ((unsigned long)(&((type *)0)->memb))  
 

 

转一篇网上对它的分析:
原文链接在这:
http://cutebunny.blog.51cto.com/301216/67517
offsetof(TYPE, MEMBER)
该宏在Linux内核代码(版本2.6.22)中定义如下:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER); 
分析:
(TYPE *)0,将 0 强制转换为 TYPE 型指针,记 p = (TYPE *)0,p是指向TYPE的指针,它的值是0。那么 p->MEMBER 就是 MEMBER 这个元素了,而&(p->MEMBER)就是MENBER的地址,而基地址为0,这样就巧妙的转化为了TYPE中的偏移量。再把结果强制转 换为size_t型的就OK了,size_t其实也就是int。
typedef __kernel_size_t  size_t;
typedef unsigned int __kernel_size_t; 
可见,该宏的作用就是求出MEMBER在TYPE中的偏移量。


http://blog.csdn.net/orzlzro/article/details/6343415


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux内核——list_for_each_entry 的相关文章

  • Linux操作系统进程的状态和转换(五态模型)

    1 进程的状态和装换 1 1进程的三态模型 按进程在执行过程中的不同情况至少要定义三种状态 运行 running 态 进程占有处理器正在运行的状态 进程已获得CPU 其程序正在执行 在单处理机系统中 只有一个进程处于执行状态 在多处理机系统
  • linux2.6.29 CFS调度详细分析

    linux2 6 29 CFS调度详细分析 众所周知 linux最新的内核采用了CFS的调度机制 网上也有不少文章对CFS调度的源码做了详细的分析 但是大部分的文章太注重细节了 所以没有把CFS的原理进行一下从整体上的概括 基于这个原因 本
  • local_irq_save和 local_irq_disable

    如果你要禁止所有的中断该怎么办 在2 6内核中 可以通过下面两个函数中的其中任何一个关闭当前处理器上的所有中断处理 这两个函数定义在
  • linux内核驱动中_IO, _IOR, _IOW, _IOWR 宏的用法与解析

    在驱动程序里 ioctl 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值 cmd除了可区别数字外 还包含有助于处理的几种相应信息 cmd的大小为 32位 共分 4 个域 bit31 bit30 2位为 区别读写 区
  • ARM 浮点运算详解

    一 早期ARM上的浮点模拟器 早期的ARM没有协处理器 所以浮点运算是由CPU来模拟的 即所需浮点运算均在浮点运算模拟器 float math emulation 上进行 需要的浮点运算 常要耗费数千个循环才能执行完毕 因此特别缓慢 直到今
  • kmalloc使用相关

    Kmalloc内存分配和malloc相似 除非被阻塞否则他执行的速度非常快 而且不对获得空间清零 Flags参数 include
  • 第十三章 网络命名空间(内核源码实现)--基于Linux3.10

    下载地址 http download csdn net detail shichaog 8620701 有两篇翻译博文 Lxc之二 网络设置 和 linuxnamespace 之使用 LXC文章中关于网络的设置是从用户空间配置的 从该文章可
  • ARM架构内核启动分析-head.S(1.1、vmlinux.lds 链接脚本分析)

    ARM架构内核启动分析 一 start kernel之前 首先需要明确的是 内核镜像在被解压之后执行 是执行哪段代码 这是个重要的问题 平时在编译生成应用程序或内核模块时 我们无需考虑链接的具体细节 如代码和数据放在哪里 代码执行入口在哪等
  • chroot命令

    转载 理解 chroot 什么是 chroot chroot 即 change root directory 更改 root 目录 在 linux 系统中 系统默认的目录结构都是以 即是以根 root 开始的 而在使用 chroot 之后
  • 虚拟文件系统 (VFS)-基于linux3.10

    引言 虚拟文件系统 VFS VirtualFileSystem 介于具体的文件系统和C库之间 其用提供一个统一的方法来操作文件 目录以及其它对象 其能够很好的抽象具体的文件系统 在linux上具体的文件系统主要分为三类 l 基于非易失性的存
  • 一文让你彻底了解Linux内核文件系统

    一 文件系统特点 文件系统要有严格的组织形式 使得文件能够以块为单位进行存储 文件系统中也要有索引区 用来方便查找一个文件分成的多个块都存放在了什么位置 如果文件系统中有的文件是热点文件 近期经常被读取和写入 文件系统应该有缓存层 文件应该
  • 带外数据

    定义带 外 数据 想 像一下在银行人们排起队等待处理他们的帐单 在这个队伍中每个人最后都会移到前面由出纳员进行服务 现在想像一下一个走入银行 越过整个队伍 然后用枪抵 住出纳员 这个就可以看作为带 外 数据 这个强盗越过整个队伍 是因为这把
  • linux支持usb打印机

    配置CONFIG USB PRINTER y inux内核默认运行打印机 核 驱动 直接在配置上CONFIG USB PRINTER y添加上去就好了 make menuconfig 选上USB打印机选项 Device Drivers gt
  • linux内核对于指令异常的处理

    1 处理流程 以arm64来介绍一下流程 如果在用户层发生指令异常时 首先进入入口el0 undef arch arm64 kernel entry s el0 undef Undefined instruction enable inte
  • 【xenclient】 使用小结 -- ubuntu的千百bug

    说道多系统 不能不提下ubuntu 以前redhat似乎是linux的领头羊 但在桌面领域 跟windows还是差得太远 在linux最弱的桌面特性上 ubuntu算是第一个以桌面特效全面超越windows的系统了 因此我的系统 除了保留做
  • 七种Linux设备驱动模型之——Device

    前言 Linux将所有的设备统一抽象为struct device结构 同时将所有的驱动统一抽象为struct device driver结构 这样设计之后就方便驱动开发工程师编写驱动 只需要将具体的设备包含struct device结构 具
  • MPC8314 (e300核) uboot 调试

    历经2个多月 完成了MPC8314最小系统 uboot 及Linux内核和根文件系统的调试 这是我第一次从头开始做小系统和内核的移植工作 虽然调试的比较辛苦 但是收获还是很多的 下面就介绍一下调试的过程和一些原理性的东西 1 MPC8314
  • Linux slab 分配器剖析

    http www ibm com developerworks cn linux l linux slab allocator 了解 Linux 内存管理的方式 良好的操作系统性能部分依赖于操作系统有效管理资源的能力 在过去 堆内存管理器是
  • int $0x80系统调用的idea

    1 基础知识 用户态和内核态 一般现代CPU都有几种不同的指令执行级别 Linux总共划分为4个指令执行级别 内核运行在0级别上 1 2级别默认不运行 用户程序运行在3级别上 在内核指令执行级别上 代码可以执行特权指令 访问任意的物理地址
  • Linux内核源码学习(1)

    一 内核简介 1 在安装好的Linux系统中 内核的源代码位于 usr src linux 2的10次方就是1K 1024 16位CPU的地址空间是64K X86结构的80386是32位CPU 段描述结构伪代码 typedef struct

随机推荐

  • 如何使用USB接口对C51单片机下载固件

    使用USB转UART芯片对单片机下载固件时会遇到的问题 C51系列单片机在下载固件的时候需要断电重启 在使用RS232接口的时候不会遇到什么困难 因为RS232不需要进行识别 但是现在使用USB转UART的芯片时会遇到问题 因为USB设备在
  • CIFAR-10训练模型(ResNet18)

    1 搭建环境 环境在实验进行时已经搭建完毕 具体步骤就不过多赘述 参考 https blog csdn net weixin 39574469 article details 117454061 接下来只需导入所需的包即可 import n
  • python中列表数据汇总和平均值_如何从记录列表中计算平均值

    所以我正在做一个作业 当从一个数据列表中计算一个平均值 数据是从一个外部的 txt文件中读取的 时 我似乎遇到了麻烦 具体来说 我要做的是从下面的数据列表中读取数据记录 在1 2 2014 Frankton 42305 67 23 12 4
  • 高德地图API INVALID_USER_SCODE问题以及keystore问题

    转载地址 http m blog csdn net article details id 50448014 请尊重原创 今天这篇文章会给大家介绍三个问题 1 接入API时出现invalid user scode问题 首先进行第一个大问题 接
  • python连接数据库设置编码_python连接mysql数据库——编码问题

    编码问题 1 连接数据库语句 在利用pycharm连接本地的mysql数据库时 要考虑到的是将数据库语句填写完整 困扰了一下午的问题就是连接语句并没有加入编码设置 db pymysql connect host localhost user
  • 如何利用计算机打印较大的字,如何在一张A4纸上打印一个超大字?

    是不是很想打印超大字 要是硬件上去了 就什么话也不用说了 可惜的是 手中只有一个A4的打印机 怎么办 还是有办法的 用Microsoft Office 2003就可以 我由于学校工作的原因 打印机只能打A4的纸 有时又想打超大字 不得不用现
  • TensorFlow零基础入门,实现手写数字识别

    TensorFlow 是一个用于人工智能的开源神器 主要为深度学习算法提供了很多函数 以及独特的运算支持 废话不多说直接上干货 我的环境 python3 7 tensorflow 1 13 2 numpy 1 20 2 1 入门示例 imp
  • 算法分享三个方面学习方法(做题经验,代码编写经验,比赛经验)

    目录 0 前言 遇到OI不要慌 只要道路对了 就不怕遥远 1 做题经验谈 1 1 做题的目的 1 2 我对于算法比赛的题目的看法 1 2 1 类似题 1 2 2 套模型 1 3 在训练过程中如何做题 1 4 一些建议 提高算法能力 1 5
  • AJAX分页以及IFRAME载入

    AJAX获取数据并分页显示 ul class movList ul div div
  • leetcode-03. 数组中重复的数字刷题笔记(c++)

    写在前面 难度 简单 unordered map 或 sort排序 大数组方法异常溢出 数据量 小数据量 数组元素作为下标 大数据量 无需map映射 耗费空间 sort排序 前后元素是否等值 题目详情 找出数组中重复的数字 在一个长度为 n
  • 一条慢SQL引发的改造

    前言 闲鱼服务端在做数据库查询时 对每一条SQL都需要仔细优化 尽可能使延时更低 带给用户更好的体验 但是在生产中偶尔会有一些情况怎么优化都无法满足业务场景 本文通过对一条慢SQL的真实改造 介绍解决复杂查询的一种思路 以及如何使得一条平均
  • Seata 处理分布式事务

    文章目录 1 Seata 简介2 2 Seata的安装 2 1 修改配置文件 2 2 在nacos上创建配置文件 seataServer yaml 2 3 安装路径seata seata server 1 6 0 seata script
  • C# —— 面向对象编程练习

    C 面向对象编程练习 基础题 代码如下 class Program static void Main string args rectangle r new rectangle Console WriteLine 调用不含参构造函数初始化后
  • [ElasticSearch]painless脚本获取字段方式及性能比较

    一 3种常见方式 doc fieldname 常用于在搜索或排序等无状态操作时进行使用 params source fieldname 也是常用在搜索或排序中 但更多用在获取额外字段时灵活操作时使用 如不获取某个字段直接使用params s
  • 基于图像形态学处理和边缘提取算法的路面裂痕检测matlab仿真

    目录 1 算法运行效果图预览 2 算法运行软件版本 3 部分核心程序 4 算法理论概述 5 算法完整程序工程 1 算法运行效果图预览 2 算法运行软件版本 matlab2022a 3 部分核心程序 Rr Cc size Image1 获取
  • 适配器模式(Adapter)

    适配器是一种结构型设计模式 它能使接口不兼容的对象能够相互合作 又称封装器模式 Wrapper 适配器模式通过封装对象将复杂的转换过程隐藏于幕后 被封装的对象甚至察觉不到适配器的存在 例如 你可以使用一个将所有数据转换为英制单位 如英尺和英
  • C#中的解构

    解构是将一个对象分割成若干部分并将其存储到新的变量中 在 C 中 解构可以方便地一次性将一个对象的多个成员的值存储到多个变量中 1解构元组 元组为方法返回多个值提供了便捷 无需创建额外的类型来承载返回的值 例如 下面这个方法使用元组返回两个
  • 创建进程函数fork的使用(Linux系统编程)

    使用fork函数创建一个进程 pid t fork void fork函数调用成功 返回两次 返回值为0 代表当前进程是子进程 返回值为非负数 代表当前进程为父进程 如果调用失败则返回 1 代码 include
  • 肝进ICU,万字真言点化八大排序——我奶奶都看得懂的算法详解

    目录 传统艺能 排序应用 插入排序 冒泡排序 希尔排序 预排序 堆排序 选择排序 快速排序 hoare 法 挖坑法 前后指针法 取中优化 小区间优化 非递归快排 归并排序 非递归归并 各类算法复杂度比较 传统艺能 小编是双非本科大一菜鸟不赘
  • linux内核——list_for_each_entry

    在Linux内核源码中 经常要对链表进行操作 其中一个很重要的宏是list for each entry 意思大体如下 假设只有两个结点 则第一个member代表head list for each entry的作用就是循环遍历每一个pos