LINUX之container_of解析

1.container_of宏的定义及实现

1> Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址。
2>接口:
container_of(ptr, type, member) 

-->ptr:表示结构体中member的地址

-->type:表示结构体类型

-->member:表示结构体中的成员
通过ptr的地址可以返回结构体的首地址
3> container_of的实现: 
#define container_of(ptr, type, member) ({      \   
 const typeof( ((type *)0)->member ) *__mptr = (ptr);    \  
  (type *)( (char *)__mptr - offsetof(type,member) );})  
其实它的语法很简单,只是一些指针的灵活应用,它分两步:
第一步,首先定义一个临时的数据类型(通过typeof( ((type *)0)->member )获得)与ptr相同的指针变量__mptr,然后用它来保存ptr的值。
说明:typeof是GNU C对标准C的扩展,它的作用是根据变量获取变量的类型《typeof关键字在linux 内核中很常见》

第二步,用(char *)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。


offsetof应用实例

  1. /* linux-2.6.38.8/include/linux/compiler-gcc4.h */  
  2. #define __compiler_offsetof(a,b) __builtin_offsetof(a,b)  
  3.   
  4. /* linux-2.6.38.8/include/linux/stddef.h */  
  5. #undef offsetof  
  6. #ifdef __compiler_offsetof  
  7. #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)  
  8. #else  
  9. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)  
  10. #endif  
  11.   
  12. #include   
  13.   
  14. struct test_struct {  
  15.     int num;  
  16.     char ch;  
  17.     float fl;  
  18. };  
  19.   
  20. int main(void)  
  21. {  
  22.     printf("offsetof(struct test_struct, num) = %d\n",   
  23.             offsetof(struct test_struct, num));  
  24.       
  25.     printf("offsetof(struct test_struct,  ch) = %d\n",   
  26.             offsetof(struct test_struct, ch));  
  27.       
  28.     printf("offsetof(struct test_struct,  fl) = %d\n",   
  29.             offsetof(struct test_struct, fl));  
  30.       
  31.     return 0;  

说明,__builtin_offsetof(a,b)是GCC的内置函数,可认为它的实现与((size_t) &((TYPE *)0)->MEMBER)这段代码是一致的。    例子输出结果:

  1. offsetof(struct test_struct, num) = 0  
  2. offsetof(struct test_struct,  ch) = 4  
  3. offsetof(struct test_struct,  fl) = 8

2.container_of实例

  1. /* linux-2.6.38.8/include/linux/compiler-gcc4.h */  
  2. #define __compiler_offsetof(a,b) __builtin_offsetof(a,b)  
  3.   
  4. /* linux-2.6.38.8/include/linux/stddef.h */  
  5. #undef offsetof  
  6. #ifdef __compiler_offsetof  
  7. #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)  
  8. #else  
  9. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)  
  10. #endif  
  11.   
  12. /* linux-2.6.38.8/include/linux/kernel.h * 
  13.  * container_of - cast a member of a structure out to the containing structure 
  14.  * @ptr: the pointer to the member. 
  15.  * @type:   the type of the container struct this is embedded in. 
  16.  * @member:    the name of the member within the struct. 
  17.  * 
  18.  */  
  19. #define container_of(ptr, type, member) ({      \  
  20.     const typeof( ((type *)0)->member ) *__mptr = (ptr);    \  
  21.     (type *)( (char *)__mptr - offsetof(type,member) );})  
  22.   
  23. #include   
  24.   
  25. struct test_struct {  
  26.     int num;  
  27.     char ch;  
  28.     float fl;  
  29. };  
  30.   
  31. int main(void)  
  32. {  
  33.     struct test_struct init_test_struct = { 99, 'C', 59.12 };  
  34.   
  35.     char *char_ptr = &init_test_struct.ch;  
  36.   
  37.     struct test_struct *test_struct = container_of(char_ptr, struct test_struct, ch);  
  38.       
  39.     printf(" test_struct->num = %d\n test_struct->ch = %c\n test_struct->fl = %f\n",   
  40.         test_struct->num, test_struct->ch, test_struct->fl);  
  41.       
  42.     return 0;  

输出结果:

  1. test_struct->num = 99  
  2. test_struct->ch = C  
  3. test_struct->fl = 59.119999



你可能感兴趣的:(linux)