关于contain_of的理解
2015-12-09 12:48
459 查看
关于contain_of的理解。
内核中有这样的一个宏:
作用是这样的:如果你获得了一个大结构体里面的一个成员的指针,那么通过这个宏,你就能获得这个结构体的指针。
假设存在这么一个结构体:
Struct student{
Type1 A;
Type2 B;
Type3 C;
};
这里的type1,2,3就是我们平时常见的int,char之类的。之所以不写具体的类型是避免还要考虑内存中字节对齐等问题。
现在用这个结构体来声明一个对象:struct student demo;
那么在内存中demo的分布应该是这样的:
—————–0x6000
A
—————- 0x6008
B
—————–0x600a
C
—————-0x600e
上面的内存地址分布都是我随意写的,因为我并没有具体type1.2.3是什么类型。
那么container_of宏的三个参数分别代表什么呢?
Ptr :指向结构体内成员的指针,比如type2 * pointer=&B
Type :这个结构体类型 ,比如 struct student
Member:结构体成员名字,比如 B
代入宏看看是什么样的?
初步的替换就是这样,但是这个里面还有宏offsetof(struct student,B),暂且不看先。
const typeof( (( struct student*)0)->B) *__mptr = (pointer); 这句代码的作用是声明了一个指针__mptr。Typeof的作用是获取变量的类型,所以__mptr的类型就是type2。然后把pointer指针的值赋给它,其实就是两个指针指向同一块内存,就是指向0x6008。
下面展开offsetof( struct student,B) 看看是什么?
回看(char )__mptr这句话的意思:把这个指针强制类型转换为(char),也就是这个指针现在是字节指针了。为什么这么做呢?因为内存存储的最基本单位都是字节。这样的转换可以用来做加减法十分方便。
综上所述,0x6008-0x0008=0x6000.这个地址也就是demo结构体的起始地址了,然后转换为struct student类型的指针。
内核中有这样的一个宏:
define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
作用是这样的:如果你获得了一个大结构体里面的一个成员的指针,那么通过这个宏,你就能获得这个结构体的指针。
假设存在这么一个结构体:
Struct student{
Type1 A;
Type2 B;
Type3 C;
};
这里的type1,2,3就是我们平时常见的int,char之类的。之所以不写具体的类型是避免还要考虑内存中字节对齐等问题。
现在用这个结构体来声明一个对象:struct student demo;
那么在内存中demo的分布应该是这样的:
—————–0x6000
A
—————- 0x6008
B
—————–0x600a
C
—————-0x600e
上面的内存地址分布都是我随意写的,因为我并没有具体type1.2.3是什么类型。
那么container_of宏的三个参数分别代表什么呢?
Ptr :指向结构体内成员的指针,比如type2 * pointer=&B
Type :这个结构体类型 ,比如 struct student
Member:结构体成员名字,比如 B
代入宏看看是什么样的?
define container_of(pointer, struct student, B) ({ \
const typeof( (( struct student*)0)->B) *__mptr = (pointer); \ ( struct student*)( (char *)__mptr - offsetof( struct student,B) );})
初步的替换就是这样,但是这个里面还有宏offsetof(struct student,B),暂且不看先。
const typeof( (( struct student*)0)->B) *__mptr = (pointer); 这句代码的作用是声明了一个指针__mptr。Typeof的作用是获取变量的类型,所以__mptr的类型就是type2。然后把pointer指针的值赋给它,其实就是两个指针指向同一块内存,就是指向0x6008。
下面展开offsetof( struct student,B) 看看是什么?
define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
替换后得到:define offsetof(struct student, B) ((size_t) &((struct student*)0)->B)
(struct student*)0)这句话的意思是把student结构体的起始地址强制制定为0,那么B的地址就是相对0地址的偏移量,然后取址,在上图中就是0x0008.回看(char )__mptr这句话的意思:把这个指针强制类型转换为(char),也就是这个指针现在是字节指针了。为什么这么做呢?因为内存存储的最基本单位都是字节。这样的转换可以用来做加减法十分方便。
综上所述,0x6008-0x0008=0x6000.这个地址也就是demo结构体的起始地址了,然后转换为struct student类型的指针。
相关文章推荐
- 调用打电话,调用发短信,发email,打开网址,打开其他第三方应用
- 创建虚拟机libvirt报错 Fail bind socket:Permission Deny
- 2014/08/23——OJ出现waiting...
- saiku中多cube排序问题
- saiku中默认级别all的国际化
- BeginPaint和GetDC的区别
- 让ubuntu开机快一点:记开机出现Waiting for network configuration...
- Daily Scrum NO.2
- AIM documentation templates
- 更新Xcode7之后报错: Assertion failure
- leetcode -- Climbing Stairs -- 简单重要
- xtrabackup版本较低触发nfs-v4的bug:cp: failed to preserve ownership: Invalid argument
- zzulioj 1809: make pair (数学转换求余简化)
- Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define 解决
- Daily Scrumming* 2015.12.8(Day 1)
- LeetCode 011 Container With Most Water
- 【转】MegaSAS RAID卡 BBU Learn Cycle周期的影响
- Daily Scrum 12.8
- nltk modules main
- lightoj1086 Jogging Trails