container_of()宏解析
来源:互联网 发布:淘宝能卖什么东西 编辑:程序博客网 时间:2024/05/18 00:20
在内核中很多地方都会使用到宏container_of()。
都知道宏container_of()的作用是:根据结构体中一个域成员变量的指针获取指向整个结构体的指针、现在来分析这个宏是如何实现的;
内核中container_of()代码如下:
/** * 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 *)0)->member)*__mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); })
内核中offsetof()代码如下:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)一、理论解析
先来说说offsetof()宏;
1. (type *)0:将0转化为TYPE型指针;
2. (TYPE *)0)->MEMBER:表示访问TYPE型指针0指向结构体的成员变量MEMBER;
3. &((TYPE *)0)->MEMBER):表示取成员变量MEMBER的地址;
4. ((size_t) :类型转化
巧妙之处在于:将0转换成(TYPE*),然后结构体以内存空间首地址0作为起始地址,则成员地址就成为偏移地址。
再来说说container_of()宏;
1. typeof(((type *)0)->member)的作用是获取成员member的结构类型;
2. typeof(((type *)0)->member)*__mptr == (ptr);表示定义临时变量__mptr,将指针ptr赋值给__mptr;
3. (type *)( (char *)__mptr - offsetof(type,member) )在(type *)作用下进行将字节型的结构体起始指针转换为type *型的结构体起始指针;
二、案例解析:
以类型struct example_st为例:
struct example_st{type_fst mem1;type_sec mem2;type_thd mem3;type_fth mem4;};
进行地址标记:
container_of(sec, struct example_st, mem2))代入宏
container_of(sec, struct example_st, mem2) ({ \const typeof(((struct example_st *)0)->mem2)*__mptr = (sec); \ (struct example_st *)((char *)__mptr - offsetof(struct example_st, mem2)); })第三行offsetof是计算mem2在结构体struct example_st,中偏移量,等于0x0008;
第二行可知__mptr = 0xa018;
第三行计算结果是:0xa018 - 0x0008 = 0xa0010;
三、程序实例
list.h
/********************************************** * Author: lewiyon@hotmail.com * File name: list.h * Description: define some macroes * Date: 2011-12-29 *********************************************/#ifndef __LIST_H#define __LIST_H//typedef unsigned long size_t;#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})#endif
test.c
/********************************************** * Author: lewiyon@hotmail.com * File name: test.h * Description: test the macroes in the core.h * Date: 2011-12-29 *********************************************/#include <malloc.h>#include "list.h"struct student{ char *name; char sex; unsigned long id; int age; int money;};static struct student *id_stu(unsigned long *id_no){ return (container_of(id_no, struct student, id));}int main(int argc, char *argv[]){ unsigned long offset; struct student *stu, *stu_tst; stu_tst = NULL; stu = (struct student *)malloc(sizeof(struct student)); stu->name = "lewiyon"; stu->sex = 'M'; stu->id = 2004035000; stu->age = 26; stu->money =0; printf("-------------------------------\n"); printf("stu = %p\n", stu); printf("&stu->name = %p\n", &stu->name); printf("&stu->sex = %p\n", &stu->sex); printf("&stu->id = %p\n", &stu->id); printf("&stu->age = %p\n", &stu->age); printf("&stu->money = %p\n", &stu->money); printf("stu->name = %s\n", stu->name); printf("-------------------------------\n"); stu_tst = id_stu(&stu->id); offset = offsetof(struct student, id); printf("offset = %p\n", offset); printf("stu_tst = %p\n", stu_tst); printf("&stu_tst->name = %p\n", &stu_tst->name); printf("&stu_tst->sex = %p\n", &stu_tst->sex); printf("&stu_tst->id = %p\n", &stu_tst->id); printf("&stu_tst->age = %p\n", &stu_tst->age); printf("&stu_tst->money = %p\n", &stu_tst->money); printf("stu_tst->name = %s\n", stu_tst->name); return 0;}
- container_of()宏的解析
- container_of宏定义 解析
- container_of()宏解析
- container_of宏定义解析
- container_of()宏的简要解析
- container_of()宏的简要解析
- container_of()宏的简要解析
- container_of()宏的简要解析
- container_of()宏的简要解析
- linux内核container_of宏解析
- Linux内核Container_of宏解析
- container_of解析
- container_of()宏的简要解析(转载)
- container_of()宏的简要解析 zz
- 深入浅出实例解析linux内核container_of宏
- container_of(ptr, type, member)宏定义解析
- container_of 解析 理解 详解
- container_of 解析 理解 详解
- Android应用程序框架层和系统运行库层日志系统源代码分析
- JAVA数字处理类使用2
- Android日志系统Logcat源代码简要分析
- android的消息Toast,提示对话框,menu,Activity替换数据传递。
- C#/C++/CLI运行效率测试之二: Native C++调用Native C++ DLL
- container_of()宏解析
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划
- 今年总结
- 如何利用C#创建和调用DLL (步骤+实例)
- 进程与线程
- JAVA高级:选择JSF不选Struts的十大理由
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析
- Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析