1.offsetof(TYPE, MEMBER)

 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

offsetof是一个自定义的宏,其返回值是一个member成员在一个type类型的结构体中相对于结构体首地址的字节偏移量;

分析其工作原理:
1.(TYPE *)0将0地址强制转换成TYPE *类型指针---------且可以认为,这个类型的结构体的首地址是0x0;
2.(TYPE *)0->MEMBER以指针形式访问成员MEMBER;
3.&((TYPE *)0->MEMBER)取成员MEMBER的地址;
因为是从0地址开始的,所以取得成员变量MEMBER的地址等于=相对与结构体首地址的偏移地址;
4.((size_t) &((TYPE *)0)->MEMBER),然后将强制类型转换成int型,作为offsetof的返回值;

2.container_of

#define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) * __mptr = (ptr);(type *)( (char *)__mptr - offsetof(type,member) );})

作用:根据一个结构体变量中的一个域成员变量的指针(也就是地址)来获取指向整个结构体变量的指针(地址)的功能
分析:
1).const typeof( ((type *)0)->member ) * __mptr = (ptr)
  typeof( ((type *)0)->member )这里获得member成员的类型;
  typeof()就是由变量名得到变量数据类型的;
2).const typeof( ((type *)0)->member ) * __mptr = (ptr)

  定义一个const typeof() * __mptr类型的指针,并初始化为ptr;这里的ptr是一个指向type类型结构体成员变量member的指针,也就是member在结构体中的地址;
3).(char *)__mptr

  这里将__mptr指针强制类型转换成char *类型:
  原因是: 如果_mptr为int *类型, _mptr - offset 相当于减去 sizeof(int)*offset个字节;
4).offsetof(type,member)

  就是一个得到member相当于结构体首地址的偏移量,以字节单位;
5).(char *)__mptr - offsetof(type,member)
  得到_mptr所在结构体的首地址;
6).(type *)( (char *)__mptr - offsetof(type,member))
  将得到的结构体首地址强制类型转换成type *类型;

3.list_for_each_entry

#define list_for_each_entry(pos, head, member)                \
for (pos = list_entry((head)->next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))

在这里,list_for_each_entry就是一个for循环:

for ( pos = list_entry((head)->next, typeof(*pos), member); prefetch(pos->member.next), &pos->member != (head); pos = list_entry(pos->member.next, typeof(*pos), member))
1) pos = list_entry((head)->next, typeof(*pos), member)

  其中:

  #define list_entry(ptr, type, member) container_of(ptr, type, member)  

  因此:

  pos = list_entry((head)->next, typeof(*pos), member)
  等价于:
  pos = container_of((head)->next, typeof(*pos), member)

  所以:pos被初始化为一个指向 结构体成员变量member所在的结构体(结构体类型为typeof(*pos))  的指针;

  由于container_of的第一个参数是head->next,所以被初始化的pos是指向头结点的下一个节点;

 2)  prefetch(pos->member.next), &pos->member != (head)

  判断是否又到达头结点,表明遍历结束

 3)  pos = list_entry(pos->member.next, typeof(*pos), member)

   是pos指向下一个链表节点;

关于宏:container_of和 offsetof以及list_for_each_entry的更多相关文章

  1. linux内核第一宏 container_of

    内核第一宏 list_entry()有着内核第一宏的美称,它被设计用来通过结构体成员的指针来返回结构体的指针.现在就让我们通过一步步的分析,来揭开它的神秘面纱,感受内核第一宏设计的精妙之处. 整理分析 ...

  2. linux内核中宏container_of是干什么的?

    Linux Kernel Version 4.14 1. container_of是干什么的? 已知一个结构体中某个成员的首指针,那么就可以通过宏container_of来获得此结构体的首指针 2 先 ...

  3. container_of 和 offsetof 宏详解

    在linux内核链表中,会遇到两个宏. 在include/linux/stddef.h中,有这样的定义 #define offsetof(TYPE, MEMBER) ((size_t) &(( ...

  4. linux内核宏container_of

    首先来个简单版本 /* given a pointer @ptr to the field @member embedded into type (usually * struct) @type, r ...

  5. (十)Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  6. Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  7. Linux内核中的常用宏container_of其实很简单【转】

    转自:http://blog.csdn.net/npy_lp/article/details/7010752 开发平台:Ubuntu11.04 编 译器:gcc version 4.5.2 (Ubun ...

  8. 剖析linux内核中的宏---------container_of

    #define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); ...

  9. linux内核宏container_of前期准备之gcc扩展关键字typeof

    typeof基本介绍 typeof(x) 这是它的使用方法,x可以是数据类型或者表达式.它的作用时期和sizeof类似,就是它是在编译器从高级语言(如C语言)翻译成汇编语言时起作用,这个很重要,稍后会 ...

随机推荐

  1. Java服务器端消息队列实战

    服务端口监听--报文接收--报文解码--业务处理--报文编码--写回客户端 从服务端与客户端成功握手并产生一个socket后,为了提高吞吐能力,接下来的事情就可以交给多线程去处理. 为了对接入的请求做 ...

  2. StringBuilder_学习笔记

    参考:https://www.jianshu.com/p/160c9be0b132 连接符号 "+" 本质 字符串变量(非final修饰)通过 "+" 进行拼接 ...

  3. windows系统设备管理器显示全部硬件

    下面的小命令能让隐藏的未卸载掉的硬件设备彻底现身:开始-运行-CMD C:\> C:\>start devmgmt.msc 之后再在Windows 的设备管理器中,单击菜单“显示”-“显示 ...

  4. 【bzoj2038】[2009国家集训队]小Z的袜子(hose) 莫队算法

    原文地址:http://www.cnblogs.com/GXZlegend/p/6803860.html 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终 ...

  5. [洛谷P3978][TJOI2015]概率论

    题目大意:对于一棵随机生成的$n$个结点的有根二叉树,所有不同构的形态等概率出现(这里同构当且仅当两棵二叉树根相同,并且相同节点的左儿子和右儿子都相同),求叶子节点个数的期望是多少? 题解:令$f_n ...

  6. 冒泡排序 [组合数学+dp]

    题面 思路 一眼看过去以为NOI2018的题出出来了= =贼吓人 首先,对于这个难度,我们有一个比较明显的结论: 一个序列的难度,等于这个东西: $hard=max(\sum_{j=i+1}^n[a_ ...

  7. 将windows文本格式转换为UNIX格式

    将windows文本格式转换为UNIX格式 1.使用sed命令来进行转换,如下: sed -e ’s,^M,,g’ textfile 其中^M的输入方法是Ctrl+V, Ctrl+M 对于批量文件的处 ...

  8. 《R语言实战》读书笔记--学习张丹日志

    从张丹的日志(http://blog.fens.me/rhadoop-r-basic/)中第九条对象看到R对象的几个总结: 1.内在属性 mode length 所有对象都有的属性 2.外部属性 at ...

  9. foj Problem 2282 Wand

     Problem 2282 Wand Accept: 432    Submit: 1537Time Limit: 1000 mSec    Memory Limit : 262144 KB Prob ...

  10. DataTable转换为实体集合

    using System; using System.Collections; using System.Collections.Generic; using System.Data; using S ...