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. 【bzoj2212】[Poi2011]Tree Rotations 权值线段树合并

    原文地址:http://www.cnblogs.com/GXZlegend/p/6826614.html 题目描述 Byteasar the gardener is growing a rare tr ...

  2. Java8并行流使用注意事项

    对于从事Java开发的童鞋来说,相信对于Java8的并行流并不陌生,没错,我们常常用它来执行并行任务,但是由于并行流(parallel stream)采用的是享线程池,可能会对我们的性能造成严重影响, ...

  3. AE中实现Control中的各种图形工具的方法

    添加命名空间 using ESRI.ArcGIS.SystemUI;using ESRI.ArcGIS.Controls; A类:前面有Controls 后面有tool的工具都可以用同一类的代码实现( ...

  4. 使用jdbc连接oracle数据库时遇到的一些问题

    第一个问题:驱动名称错误 错误截图如下: 从错误提示可以看出,oracle少写了一个'a',手误对程序员来说是经常发生的事,有时能够及时发现纠错,有时就容易忽略. 建议大家将写好的测试无误的保存起来, ...

  5. 借教室(NOIP2012)

    原题传送门 其实就是求能满足多少个订单.. 然后搞上差分, 又因为如果前n个能够满足,那么前m个一定能满足(m<n) 所以可以二分(重点!) 然后乱搞..就AC了(其实也挺麻烦的...233~) ...

  6. v4l2 spec 中文 Ch01【转】

    转自:http://blog.csdn.net/wuhzossibility/article/details/6638245 目录(?)[-] Chapter 1 通用APICommon API El ...

  7. Centos7下zabbix部署(五)定义报警媒介-微信

    1.注册微信 注册过程参考地址:https://www.cnblogs.com/hanyifeng/p/5368102.html 主要需要以下一些信息 CorpID :     wwxxxxxxxxx ...

  8. 重启服务器“AH00558: apache2: Could not reliably determine the server's fully qualified domain name”问题的解决

    重启服务器时报错: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, u ...

  9. iOS手势UIGestureRecognizer的使用失效问题

    问题:视图正常展示在界面中,父层是放在window上的,底部的一个控件的点击事件失效(所有设置都正常) 解决思路:虽然视图能够正常展示,但是发现父类视图的底部尺寸比子类的视图的尺寸小,也就是说上层视图 ...

  10. 性能优化之基础资源cpu&内存(JVM)

    本章主要介绍计算机的一些基础资源以及操作系统处理后的一些基础资源. 主要包括 cpu 内存 磁盘 网络 线程 本章会介绍这些资源的一些原理,介绍如何查看资源的数量,使用情况,对性能和整体计算机执行的一 ...