container_of(ptr,type,member) 用于在已知结构体里面成员member和该成员指针ptr(就是地址)和结构体类型type, 返回该成员所在的结构体的指针(就是地址), 例如已知
  1. struct student a {
  2. char *name;
  3. int age;
  4. }
  5. int *page = &age;
  6. container_of(page, struct student, a.age); 返回a的地址

实现该方法可以分三步:
0 算出a.age在a里面的偏移,可以通过将零地址强制转换成struct student格式, (struct student *)0, 那么  ((struct student *)0)->age 即是偏移大小
1 已知a.age地址和在a里面的偏移,即可通过a.age 地址减去偏移得到a的地址, (char *) page - ((struct student *)0)->age
2 最后将得到的地址强制 转换成struct student 格式, (struct student *)((char *)page - ((struct student *)0)->age) 即为所求的指针
根据我们的思路看内核里面的实现, 果然跟我们所想的一样

  1. kernel.h
  2. #define container_of(ptr, type, member) ({            \
  3. const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
  4. (type *)( (char *)__mptr - offsetof(type,member) );})
  5. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

转自:http://blog.csdn.net/hellowxwworld/article/details/11072683

该宏定义在kernel.h中;

原型为#define container_of(ptr, type, member) ({\
    const typeof( ((type *)0)->member ) *__mptr = (ptr);\
    (type *)( (char *)__mptr - offsetof(type,member) );})
 其中 ptr是指向正被使用的某类型变量指针;type是包含ptr指向的变量类型的结构类型;member是type结构体中的成员,类型与ptr指向的变量类型一样。
功能是计算返回包含ptr指向的变量所在的type类型结构变量的指针。(比较拗口)
该宏的实现思路:计算type结构体成员member在结构体中的偏移量,然后ptr的地址减去这个偏移量,就得出type结构变量的首地址。
该宏的实现方法:1、通过typeof关键字定义一个与type结构体的member成员相同的类型的变量
__mptr且将ptr值赋给它。
             2、用宏offsetof(type,member),获取member成员在type结构中的偏移量
(原型:offsetof(TYPE,MEMBER) ((size_t)&(TYPE *)0)->MEMBER). 定义在stddef.h.)
             3、最后将__mptr值减去这个偏移量,就得到这个结构变量的地址了(亦指针)。

typeof是个关键字,可用来引用宏参数的类型。

转自:http://blog.chinaunix.net/uid-24467128-id-2606205.html

(转)内核container_of(ptr,type,member) 解析的更多相关文章

  1. list_entry(ptr, type, member)——知道结构体内某一成员变量地址,求结构体地址

    #define list_entry(ptr, type, member) \ ((type *)(() -> member))) 解释: 1 在0这个地址看做有一个虚拟的type类型的变量,那 ...

  2. 对list_entry(ptr, type, member)的理解

    如何根据一个结构体成员的地址.结构体类型以及该结构体成员名获得该结构体的首地址? #define list_entry(ptr, type, member) \ ((type *)((char *)( ...

  3. 刨一刨内核container_of()的设计精髓

    新年第一帖,总得拿出点干货才行,虽然这篇水分还是有点大,大家可以晒干了温水冲服.这段时间一直在整理内核学习的基础知识点,期间又碰到了container_of()这个宏,当然还包括一个叫做offseto ...

  4. linux内核container_of宏定义分析

    看见一个哥们分析container_of很好,转来留给自己看 一.#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMB ...

  5. 鸿蒙内核源码分析(ELF解析篇) | 你要忘了她姐俩你就不是银 | 百篇博客分析OpenHarmony源码 | v53.02

    百篇博客系列篇.本篇为: v53.xx 鸿蒙内核源码分析(ELF解析篇) | 你要忘了她姐俩你就不是银 | 51.c.h.o 加载运行相关篇为: v51.xx 鸿蒙内核源码分析(ELF格式篇) | 应 ...

  6. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

    #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)宏的运行机理:1. ( (TYPE *)0 ) 将零转型为TY ...

  7. Linux内核很吊之 module_init解析 (下)【转】

    转自:https://blog.csdn.net/richard_liujh/article/details/46758073 版权声明:本文为博主原创文章,未经博主允许不得转载. https://b ...

  8. The specified type member 'IsLock' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

    var query = from C in objDb.GetDb<A>() join a in objDb.GetDb<B>().Where(m => m.Comput ...

  9. #define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

    #include <iostream> #define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) usi ...

随机推荐

  1. shiny安装使用入门

    下载最新版R(至少3.2.5版本),在CRAN上下载: 打开R install.packages("shiny")#安装shiny包 library(shiny)#如果出现warn ...

  2. JavaScript严格模式下this指向

    一般认为:严格模式下this不允许指向全局对象.是函数体是否处于严格模式! 如:http://www.ruanyifeng.com/blog/2013/01/javascript_strict_mod ...

  3. 百度地图总结第二篇--POI检索功能

    简单介绍: 眼下百度地图SDK所集成的检索服务包含:POI检索.公交信息查询.线路规划.地理编码.行政区边界数据检索.在线建议查询.短串分享(包含POI搜索结果分享.驾车/公交/骑行/步行路线规划分享 ...

  4. 公用的css

    /*公共开始*/ body, ol, ul, h1, h2, h3, h4, h5, h6, p, th, td, dl, dd, form, fieldset, legend, input, tex ...

  5. 数据库如何创建视图create view

    数据库如何创建视图     创建视图的理想步骤: 一般来说,视图创建可以分为五步走: 第一步:先考虑select语句的编写.我们知道,视图其实就是一个select语句的集合,所以,我们建立视图的第一步 ...

  6. 【LeetCode】66. Plus One (2 solutions)

    Plus One Given a non-negative number represented as an array of digits, plus one to the number. The ...

  7. 简单hello world

    第一步配置路由: 打开app/http/route.php文件,输入:Route::get('/home', 'HomeController@index'); 第二步配置控制器: 控制文件可以手动添加 ...

  8. 树莓派/RaspberryPi 内核源码下载

    树莓派的源码有两种下载方式:压缩包下载和git clone指令下载. 1.压缩包下载 选择对应分支,点击Github界面的 下载按钮即可,如下图: 测试发现,同样的分支,用压缩包方式下载后编译会出错, ...

  9. python 中 numpy array 中的维度

    简介 numpy 创建的数组都有一个shape属性,它是一个元组,返回各个维度的维数.有时候我们可能需要知道某一维的特定维数. 二维情况 >>> import numpy as np ...

  10. mysql 字面值

    mysql 数据库中实现了许多的数据类型.通常我们用的最多的是在建表的时候指定列的数据类型 如:brithday date default '2000-01-01' 那么我们如何给字面值(直接量)指定 ...