list_for_each_entry
内核里面用list_for_each_entry实在太多了,定义在linux-3.10/include/linux/list.h:
/**
* 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_struct within the struct.
*/
#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)) /**
* 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_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
要分析list_entry就得分析container_of,linux-3.10/include/linux/kernel.h:
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *))->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
宏定义的第一行:typeof(x)是gcc预处理,获取x的类型,这里((type *)0)->member利用p=0的指针指向相应结构体(type)的成员,typeof获取该成员的类型并定义__mptr。
第二行:#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER),跟第一行的((type *)0)->member一个样子,获取结构体(type)的偏移量,最后__mptr转换成(char *)减去自己在结构体(type)的偏移量得到结构体(type)的指针。
可以看出第一行在功能上是没有什么卵用,其实只是作为类型检测,实现一个给定成员类型(member)的指针(ptr)找到这个成员的结构体(type)功能的只在第二行。
返回看list_entry(ptr, type, member)其实就是通过ptr找到type。
再回到list_for_each_entry(pos, head, member)的实现可以知道,用list_head通过list_entry找到包含next list_head的结构体(pos)作为变量进行循环。可得要使用list_for_each_entry,struct pos里面的成员必须包含list_head。所以在linux里面的struct经常看到list_head这个成员就是这个道理
list_for_each_entry的更多相关文章
- list_for_each与list_for_each_entry具体解释
一.list_for_each 1.list_for_each原型#define list_for_each(pos, head) \ for (pos = (head)->next, ...
- list_for_each_entry解析
双向链表及链表头: 建立一个双向链表通常有一个独立的用于管理链表的链表头,链表头一般是不含有实体数据的,必须用INIT_LIST_HEAD()进行初始化,表头建立以后,就可以将带有数据结构的实体链表成 ...
- 关于宏:container_of和 offsetof以及list_for_each_entry
1.offsetof(TYPE, MEMBER) #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) offse ...
- 关于container_of和list_for_each_entry 及其相关函数的分析
Linux代码看的比较多了,经常会遇到container_of和list_for_each_entry,特别是 list_for_each_entry比较多,因为Linux经常用到链表,虽然知道这些函 ...
- list_for_each_entry()函数分析
list_for_each原型: #define list_for_each(pos, head) \ for (pos = (head)->next, prefetch(pos->nex ...
- IIC驱动移植在linux3.14.78上的实现和在linux2.6.29上实现对比(deep dive)
首先说明下为什么写这篇文章,网上有许多博客也是介绍I2C驱动在linux上移植的实现,但是笔者认为他们相当一部分没有分清所写的驱动时的驱动模型,是基于device tree, 还是基于传统的Platf ...
- spi子系统之驱动SSD1306 OLED
spi子系统之驱动SSD1306 OLED 接触Linux之前,曾以为读源码可以更快的学习软件,于是前几个博客都是一边读源码一边添加注释,甚至精读到每一行代码,实际上效果并不理想,看过之后就忘记了.主 ...
- class.c 添加中文注释(3)
int class_device_register(struct class_device *class_dev) { /* [cgw]: 初始化一个struct class_device */ cl ...
- Linux 2.6内核中新的锁机制--RCU
转自:http://www.ibm.com/developerworks/cn/linux/l-rcu/ 一. 引言 众所周知,为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁 ...
随机推荐
- yii常用操作函数
<?php defined('YII_DEBUG') or define('YII_DEBUG', true); //当在调试模式下,应用会保留更多日志信息,如果抛出异常,会显示详细的错误调用堆 ...
- 常用的机器学习&数据挖掘知识点
Basis(基础):MSE(Mean Square Error 均方误差),LMS(LeastMean Square 最小均方),LSM(Least Square Methods 最小二乘法),MLE ...
- 【CodeChef】Enormous Input Test
The purpose of this problem is to verify whether the method you are using to read input data is suff ...
- 转载:ensemble计划和数据库
原文来源:x2yline在生信进化树上的评论,http://www.biotrainee.com/thread-626-1-1.html Ensemble( ensembl.org网站是常用真核生物参 ...
- JavaWeb 文件上传下载
1. 文件上传下载概述 1.1. 什么是文件上传下载 所谓文件上传下载就是将本地文件上传到服务器端,从服务器端下载文件到本地的过程.例如目前网站需要上传头像.上传下载图片或网盘等功能都是利用文件上传下 ...
- java基础(2)-面向对象(2)
构造方法 构造方法特点 方法名与类名相同 方法名前没有返回值类型的声明(void也没有) 方法中不能使用return语句返回一个值 创建对象时自动调用并执行 如果类中没有自定义构造方法,则java调用 ...
- SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法
软件152 尹以操 首先谢谢大佬的简书文章:http://www.jianshu.com/p/45ad65690e33# 这篇文章中讲的是spring中使用spring data jpa,使用了xml ...
- Flume的Avro Sink和Avro Source研究之二 : Avro Sink
啊,AvroSink要复杂好多:< 好吧,先确定主要问题: AvroSink为啥这么多代码?有必要吗?它都有哪些逻辑需要实现? 你看,avro-rpc-quickstart里是这么建client ...
- pandas read_sql与read_sql_table、read_sql_query 的区别
一:创建链接数据库引擎 from sqlalchemy import create_engine db_info = {'user':'user', 'password':'pwd', 'host': ...
- openstack nova 基础知识——Quota(配额管理)
一.什么是配额(quota)管理 简单的讲就是控制用户资源的数量.在openstack里,管理员为每一个工程(project)分配的资源都是有一定限制的,这些资源包括实例(instance).cpu. ...