博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux内核container_of宏定义分析
阅读量:5054 次
发布时间:2019-06-12

本文共 1904 字,大约阅读时间需要 6 分钟。

看见一个哥们分析container_of很好,转来留给自己看

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

1. ( (TYPE *)0 ) 将零转型为TYPE类型指针;
2. ((TYPE *)0)->MEMBER 访问结构中的数据成员;
3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址;
4.(size_t)(&(((TYPE*)0)->MEMBER))结果转换类型;
巧妙之处在于将0转换成(TYPE*),结构以内存空间首地址0作为起始地址,则成员地址自然为偏移地址。
举例说明:
#include<stdio.h>
typedef struct _test
{
      char i;
      int j;
      char k;
}Test;
int main()
{
      Test *p = 0;
      printf("%p\n", &(p->k));
}
答案:00000008
自 己分析:这里使用的是一个利用编译器技术的小技巧,即先求得结构成员变量在结构体中的相对于结构体的首地址的偏移地址,然后根据结构体的首地址为0,从而 得出该偏移地址就是该结构体变量在该结构体中的偏移,即:该结构体成员变量距离结构体首的距离。在offsetof()中,这个member成员的地址实 际上就是type数据结构中member成员相对于结构变量的偏移量。对于给定一个结构,offsetof(type,member)是一个常 量,list_entry()正是利用这个不变的偏移量来求得链表数据项的变量地址。

二、container_of()

container_of() 来自\linux\kernel.h
内核中的注释:container_of - cast a member of a tructure 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 truct.

#define container_of(ptr, type, member) ({ \

const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})

自己分析:

1.(type *)0->member为设计一个type类型的结构体,起始地址为0,编译器将结构体的起始的地址加上此结构体成员变量的偏移得到此结构体成员变 量的偏移地址,由于结构体起始地址为0,所以此结构体成员变量的偏移地址就等于其成员变量在结构体内的距离结构体开始部分的偏移量。即:& (type *)0->member就是取出其成员变量的偏移地址。而其等于其在结构体内的偏移量:即为:(size_t)(& ((type *)0)->member)经过size_t的强制类型转换后,其数值为结构体内的偏移量。该偏移量这里由offsetof()求出。
2.typeof( ( (type *)0)->member )为取出member成员的变量类型。用其定义__mptr指针.ptr为指向该成员变量的指针。__mptr为member数据类型的常量指针,其指向ptr所指向的变量处。
3.(char *)__mptr转换为字节型指针。(char *)__mptr - offsetof(type,member))用来求出结构体起始地址(为char *型指针),然后(type *)( (char *)__mptr -offsetof(type,member) )在(type *)作用下进行将字节型的结构体起始指针转换为type *型的结构体起始指针。
4.({ })这个扩展返回程序块中最后一个表达式的值。
      这就是从结构体某成员变量指针来求出该结构体的首指针。指针类型从结构体某成员变量类型转换为该结构体类型

转自:http://www.cnitblog.com/puppypyb/archive/2008/08/20/48172.aspx

转载于:https://www.cnblogs.com/jiuyueguang/p/3190801.html

你可能感兴趣的文章
[译] Javascript初学者需要知道的十件事
查看>>
分糖果(模拟)
查看>>
linux命令,vim,vi 说明
查看>>
34 String、StringBuffer、StringBuilder
查看>>
LINUX下SYN攻防战 [转]
查看>>
C# 导出Word报”无法打开Office open xml文件。因为文件内容有错误“ 解决方法
查看>>
Linux内核_实验三:跟踪分析Linux内核的启动过程
查看>>
电脑是怎样识别USB3.0 U盘的
查看>>
Unity 捕获IronPython脚本错误
查看>>
word批量打印工具,c#写的
查看>>
Asp.Net MVC学习总结(一)——Asp.Net MVC简单入门
查看>>
Python学习第四篇——列表访问与判定
查看>>
JavaScript
查看>>
配置SVTI
查看>>
light oj 1138 - Trailing Zeroes (III)(阶乘末尾0)
查看>>
Windows如何自定义U盘盘符、文件夹图标、文件夹背景
查看>>
非常不错的WCF入门文章,来自Artech
查看>>
ColumnView.ShownEditor Event
查看>>
nodejs pipe实现大文件拷贝
查看>>
javascript之定义函数时 this 和prototype区别
查看>>