list_for_each_entry解析
双向链表及链表头:
建立一个双向链表通常有一个独立的用于管理链表的链表头,链表头一般是不含有实体数据的,必须用INIT_LIST_HEAD()进行初始化,表头建立以后,就可以将带有数据结构的实体链表成员加入到链。
INIT_LIST_HEAD (&nphy_dev_list);
定义:
#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))
它实际上是一个 for 循环,利用传入的 pos 作为循环变量,从表头 head 开始,逐项向后(next 方向)移动 pos,直至又回head.

我们将for循环分解为一下三点:
1. for循环初始化 pos = list_entry((head)->next, typeof(*pos), member);
2. for循环执行条件 &pos->member != (head);
3. 每循环一次执行 pos = list_entry(pos->member.next, typeof(*pos), member))
typeof()是取变量的类型,这里是取指针pos所指向数据的类型。
先看第一个:
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *))->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
讲讲container_of:作用:根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针。
所以(type *)0)就是将0强转为一个地址,这个地址(0x0000)指向的是类型type的数据。当然,这里是一个技巧,并不是真的在地址0x0000存放了我们的数据。
((type *)0)->member的作用,这里的‘->’很显然是通过指针指取结构体成员的操作。指针就是刚才通过0强转的地址。所以也就是相当于地址0x0000 是结构体类型type的首地址,通过->’取其中的成员变量member。
typeof( ((type *)0)->member ) *__mptr = (ptr):知道member成员的类型,定义一个指针变量__mptr,指向的类型是member的类型,其初始化为ptr的值
offsetof(type,member):求出member在结构体中的偏移量
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
根据优先级的顺序,最里面的小括号优先级最高,TYPE *将整型常量0强制转换为TYPE型的指针,且这个指针指向的地址为0,也就是将地址0开始的一块存储空间映射为TYPE型的对象,接下来再对结构体中MEMBER成员进行取址,而整个TYPE结构体的首地址是0,这里获得的地址就是MEMBER成员在TYPE中的相对偏移量。再将这个偏移量强制转换成size_t型数据(无符号整型)。
(char *)__mptr - offsetof(type,member)就是__mptr - offset,即member类型的指针减去member在结构体中的偏移量。
小结:通过上面的分析,和定义出的注释,container_of的作用很明显了 -- 获得结构体的地址。那么我们需要给他提供三个参数,分别是:ptr:member成员的指针 type:结构体类型 member:成员member的名字。
这样我们就能通过container_of(ptr, type, member)的返回值,得到结构体的地址。
list_for_each_entry解析的更多相关文章
- 基于tiny4412的Linux内核移植 --- aliases节点解析
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- driver_register()函数解析
driver_register()函数解析 /** * driver_register - register driver with bus * @drv: driver to register * ...
- linux percpu机制解析【转】
转自:http://blog.csdn.net/wh8_2011/article/details/53138377 一.概述 每cpu变量是最简单也是最重要的同步技术.每cpu变量主要是数据结构数组, ...
- Linux之进程的等待与其内核实现解析
进程通过fork产生子进程,进程也会死亡,进程退出的时候将会进行内核清理,释放所有进程的资源,资源包括:内存资源,文件资源,信号量资源,共享内存资源,或者引用计数减一,或者彻底释放. 不过进程 ...
- 基于tiny4412的Linux内核移植 --- aliases节点解析【转】
转自:https://www.cnblogs.com/pengdonglin137/p/5252348.html 阅读目录(Content) 作者信息 平台简介 正文 回到顶部(go to top) ...
- xenomai内核解析之信号signal(二)---xenomai信号处理机制
xenomai信号 上篇文章讲了linux的信号在内核的发送与处理流程,现在加入了cobalt核,Cobalt内核为xenomai线程提供了信号机制.下面一一解析xenomai内核的信号处理机制. 1 ...
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- .NET Core中的认证管理解析
.NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...
- Html Agility Pack 解析Html
Hello 好久不见 哈哈,今天给大家分享一个解析Html的类库 Html Agility Pack.这个适用于想获取某网页里面的部分内容.今天就拿我的Csdn的博客列表来举例. 打开页面 用Fir ...
随机推荐
- Linux下tomcat启动
在Linux系统下,重启Tomcat使用命令操作的! 首先,进入Tomcat下的bin目录 cd /usr/local/tomcat/bin 使用Tomcat关闭命令 ./shutdown.sh 查看 ...
- android sdk屏幕截图工具
调用android sdk中的工具,在开发板上截图. 使用usb线连接android设备,打开adb调试. 进入目录 sdk/tools/ 运行 traceview.bat 运行 uiautomato ...
- tinycore remaster方法
11.1. PrerequisitesYou need a Linux distribution with the required programs available:cpio, tar, gzi ...
- querySelectorAll 和getElementsByClassName的区别
querySelectorAll 返回的是映射 改变其值不会改变document 而getElementsByClassName 改变它就会改变document 摘自JavaScript权威指南(jQ ...
- 【代码备份】pocs.m
超分辨率算法代码 POCS算法,凸集投影法. pocs.m,没有调用的代码,没看懂..只有这个函数..抱歉. function y = pocs(s,delta_est,factor) % POCS ...
- CodeForces 42C Safe cracking 规律题
题目链接:点击打开链接 3个数为一组,找最大的一个数让它降低,则显然是有解的,分类讨论一下就可以 #include<cstdio> #include<cstring> #inc ...
- 计算某个目录下所有文件的MD5值
#!/usr/bin/env python #-*- coding:utf-8 -*- ''' 计算某个目录下所有文件的MD5值 ''' import os import sys import has ...
- 全链路追踪spring-cloud-sleuth-zipkin
微服务架构下 多个服务之间相互调用,在解决问题的时候,请求链路的追踪是十分有必要的,鉴于项目中采用的spring cloud架构,所以为了方便使用,便于接入等 项目中采用了spring cloud s ...
- java前后台开发之后台自动上传下载
package downloadTest; import java.io.BufferedReader; import java.io.File; import java.io.FileInputSt ...
- sql中字段名中包含特殊字符的查询方法
sql中字段名章包含特殊字符的查询方法:例如包含"",student表中字段为:id“学号”.name"姓名". 解决办法:用英文下的 "`" ...