内核源码之 container_of(宏)

本贴最后更新于 1843 天前,其中的信息可能已经沧海桑田

内核源码之 container_of

在学习驱动的过程中发现一个很有意思的东西,就是 container_of 这个宏!
首先介绍下这个宏的功能:从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址。
然后我们来看一下这个宏在内核源码中是如何定义:

/* include/linux/kernel.h: * 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) );})

在这个宏中还使用了另外一个宏:

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

第一次看到这个宏的时候感觉很迷,不过这丝毫不能阻挡我把它弄懂的决心!接下来参考了几篇文章,差不多懂了。^^

container_of(ptr, type, member)先看看这三个参数,ptr 是你已经得到的一个成员变量的指针,type 是结构体类型,member 是 type 中 ptr 指向的那个成员变量的名称。
举个简单的例子:

struct student { char name[32]; int age; double score; }; struct student *zkw_p; struct student zkw= {"zkw", 21, 94}; int *p = &(zkw.age); //通过这个宏,传入p,以及它的结构体类型和对应的名称就得到了指向这个结构体指针。 zkw_p= container_of(p, struct student, age);
  • 仅仅知道如何使用时不够的,接下来看看到底是怎么实现的。
const typeof( ((type *)0)->member ) *__mptr = (ptr);

先看这一行,(type *)0 将 0 转化为结构体指针类型,然后访问 member 成员,接着用 typeof()得到((type *)0)->member 的类型,看到这里可能有人会问 typeof()是什么操作?我也是刚刚 get 到的(又是知识盲区啊!!)举个例子就懂了:

int var; typeof(var) var2;//等价于int var2; 很简单吧!

继续,typeof( ((type *)0)->member ) 很明了了吧!就是 member 成员的类型;这一整行代码就是 member 的类型的一个指针变量,然后把
ptr 指针赋值给了__mptr ,此时你一定会产生一个疑问,这操作有什么用,直接计算不好吗?这就是和大佬的差距啊,这是考虑到编程人员在传参时 ptr 和 member 类型匹配不上,加上这句之后类型出错之后再编译过程中编译会给出警告。(这设计很巧妙!)

(type *)( (char *)__mptr - offsetof(type,member) );

这行代码得先说下 offsetof 这个宏:

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

TYPE 结构体,MEMBER 成员变量,相当于把结构体放在 0 地址处,然后去取成员变量的地址,取出地址再转化整 size_t 就是偏移的字节数;

__mptr 减去偏移量那么就得到了结构体的首地址。

还有一点,就是你把这个宏展开后你会发现长相比较奇特:
比如:

var = ({ const typeof( ((struct student *)0)->age ) *__mptr = (p); (struct student *)( (char *)__mptr - ((size_t) &((struct student *)0)->age) ); });

他的值是代码块最右边的表达式的值,这一点有点像逗号表达式,第一次见到这种用法。

到这里这个宏的解析算是完成了!

内核中的代码随便几行都覆盖了我知识点的盲区,非常细节,处于好奇研究了下这段代码。

  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    955 引用 • 944 回帖
  • 内核
    10 引用 • 14 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 683 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 496 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 248 回帖
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 521 关注
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    115 引用 • 319 回帖
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 15 关注
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    89 引用 • 1251 回帖 • 393 关注
  • 旅游

    希望你我能在旅途中找到人生的下一站。

    100 引用 • 905 回帖
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 199 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 3 关注
  • Access
    1 引用 • 3 回帖 • 3 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    694 引用 • 537 回帖 • 1 关注
  • 音乐

    你听到信仰的声音了么?

    62 引用 • 512 回帖
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    326 引用 • 1395 回帖
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 649 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    300 引用 • 768 回帖
  • 职场

    找到自己的位置,萌新烦恼少。

    127 引用 • 1708 回帖 • 1 关注
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    21 引用 • 31 回帖 • 1 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 78 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    37 引用 • 157 回帖 • 1 关注
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 799 关注
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    22 引用 • 148 回帖 • 9 关注
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 3 关注
  • SVN

    SVN 是 Subversion 的简称,是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统,它的设计目标就是取代 CVS。

    29 引用 • 98 回帖 • 698 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 85 关注
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    93 引用 • 122 回帖 • 616 关注