曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6542|回复: 0
打印 上一主题 下一主题

[宏] container_of 实现原理分析

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2009-9-1 22:58:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
container_of() 宏的作用是通过结构体成员的指针找到对应结构体的指针,这个技巧在 linux 内核编程中十分常用。下面以实例来分析一下实现原理。

在 open() 操作里,第一个参数是,struct inode 结构体的指针。在 struct inode 结构体里,有一个 i_cdev 域,这个是一个指向 cdev 结构体的指针。在编写驱动程序时,一般情况下,不会单独的把 cdev 结构体拿出来用,而是将其封装在与驱动程序紧密相联的一个自定义的结构体里。借用 << linux device drivers 3>> 里的这么一种结构体的定义:

struct scull_dev {
            struct scull_qset *data;
            int quantum;
            unsigned long size;
            unsigend int access_key;
            struct semaphore sem;
            struct cdev cdev;
};

下面通过 container_of() 宏来获取 scull_dev 这个结构体的指针:
container_of ( inode->i_cdev, struct scull_dev, cdev);

container_of() 宏中,第 1 个参数就是 struct scull_dev 这种结构体中 cdev 成员的指针;第 2 个参数是 struct_scull 类型结构体;第 3 个参数就是 cdev 结构体。

在 <linux/kernel.h> 头文件中,可以看到 container_of() 宏的定义:
#define container_of(ptr, type, member) ({            \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})
以 struct scull_dev 作为分解宏的参数展开并分析这个宏定义:

(type *)0 欺骗编译器,说 0 地址是一个 struct scull_dev 类型结构体的指针;

((type *)0)->member 指向的就是 c_dev 结构体;

typeof ( ((type *)0)->member) 是取得 member 类型的类型,这里也就是取得 cdev 结构体的类型,即 struct cdev ;

const typeof ( ((type *)0->member) *__mptr  定义了一个 struct cdev 类型的指针 __mptr ;

const typeof ( ((type *)0->member) *__mptr = (ptr) 是将 ptr 指针赋给 __mptr , 这个赋值的目的是要取得 cdev 这个成员定义在 scull_dev 中的位置,这在下面的第 2 条语句中会用到这个位置

第一条语句分析完,下面分析第 2 条语句:

在这条语句中,offsetof(type, member) 是取得 member 参数在 type 类型结构体中的偏移位置。offsetof() 也是一个宏,它的详细情况见http://www.groad.net/bbs/read.php?tid-1040.html
在这里也就是,取得 cdev 成员在 scull_dev 中的偏移。

(char *)__mptr - offsetof(type, member) 是 __mptr 指针往上走 offsetof(type, member) 个偏移量,也就是到达了 scull_dev 这个结构体的头部,所以到此已经获得了 scull_dev 结构体的头地址了。

最后 (type *) ((char *)__mptr - offsetof(type, member)) 是把 scull_dev 结构体头部地址转换为 scull_dev 结构体类型,也就是说至此已经获得了 container_of() 宏中第 2 个参数的指针。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-4 05:04 , Processed in 0.060268 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表