Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1569842
  • 博文数量: 204
  • 博客积分: 2215
  • 博客等级: 大尉
  • 技术积分: 4426
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-06 08:03
个人简介

气质,源于心灵的自信!

文章存档

2018年(1)

2017年(1)

2016年(1)

2015年(18)

2014年(20)

2013年(30)

2012年(119)

2011年(14)

分类: LINUX

2011-10-23 12:43:44

基础知识:

1、  typeof

typeof并非ISO C的关键字,而是gccC的一个扩展。typeof是一个关键字(类似sizeof),用于获取一个表达式的类型。

举个简单的例子:

char tt;

typeof(tt) cc;

typeof(tt)等价于char,即相当于声明了char cc;

 

2、  offsetof

位置:

用途:获取结构类型TYPE里的 成员MEMBER 在结构体内的偏移

分析:

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

       假设有结构体uio_mem

struct uio_mem

{

struct kobject kobj;

              unsigned long addr;

              unsigned long size;

              int memtype;

              void __iomem *internal_addr;

};

如果想获得成员memtypeuio_mem内的偏移,那么该怎么做呢?

很简单,只要使用offsetof(struct uio_mem, memtype)就可以了。

可以将上述表达式展开为:

(size_t) &(( struct uio_mem *)0)-> memtype

( struct uio_mem *)00强制转换为struct uio_mem的指针,记为p = ( struct uio_mem *)0p是指向struct uio_mem的指针,值为0。而p->memtype则指向struct uio_mem的成员memtype,再取地址&(p->memtype),这样就得到了成员memtype的地址。由于结构体基地址p0,所以&(p->memtype)就是相对于p的偏移了。最后再把成员的地址强制转换为size_t,其实就是转换为int

typedef __kernel_size_t  size_t;
typedef unsigned int __kernel_size_t;

      

       此例中offsetof(struct uio_mem, memtype) = sizeof(struct kobject) + sizeof(unsigned long) + sizeof(unsigned long)

参考:http://cutebunny.blog.51cto.com/301216/67517

3、  container_of

位置:

用途:通过指向成员member的指针ptr,获取包含该成员的结构体type的指针

分析:

              #define container_of(ptr, type, member) ({                /

                     const typeof( ((type *)0)->member ) *__mptr = (ptr);       /

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

假设有结构体uio_mem

struct uio_mem

{

struct kobject kobj;

              unsigned long addr;

              unsigned long size;

              int memtype;

              void __iomem *internal_addr;

};

现有指向uio_mem的成员memtype的指针p(因此p的类型为int *),那么如何获取结构体uio_mem的指针?恭喜你,答对了,使用container_of(p, struct uio_mem, memtype)

将该宏展开为:

const typeof( ((struct uio_mem *)0)-> memtype) *__mptr = (p);// 1

(struct uio_mem *)( (char *)__mptr - offsetof(struct uio_mem, memtype) ); // 2

根据之前的分析,可以

该帖中所包含的都是在阅读内核代码时需要了解的一些基本概念,后续还会不断增加的,欢迎大家批评指正,谢谢。

 

1、  typeof

typeof并非ISO C的关键字,而是gccC的一个扩展。typeof是一个关键字(类似sizeof),用于获取一个表达式的类型。

举个简单的例子:

char tt;

typeof(tt) cc;

typeof(tt)等价于char,即相当于声明了char cc;

 

2、  offsetof

位置:

用途:获取结构类型TYPE里的 成员MEMBER 在结构体内的偏移

分析:

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

       假设有结构体uio_mem

struct uio_mem

{

struct kobject kobj;

              unsigned long addr;

              unsigned long size;

              int memtype;

              void __iomem *internal_addr;

};

如果想获得成员memtypeuio_mem内的偏移,那么该怎么做呢?

很简单,只要使用offsetof(struct uio_mem, memtype)就可以了。

可以将上述表达式展开为:

(size_t) &(( struct uio_mem *)0)-> memtype

( struct uio_mem *)00强制转换为struct uio_mem的指针,记为p = ( struct uio_mem *)0p是指向struct uio_mem的指针,值为0。而p->memtype则指向struct uio_mem的成员memtype,再取地址&(p->memtype),这样就得到了成员memtype的地址。由于结构体基地址p0,所以&(p->memtype)就是相对于p的偏移了。最后再把成员的地址强制转换为size_t,其实就是转换为int

typedef __kernel_size_t  size_t;
typedef unsigned int __kernel_size_t;

      

       此例中offsetof(struct uio_mem, memtype) = sizeof(struct kobject) + sizeof(unsigned long) + sizeof(unsigned long)

参考:http://cutebunny.blog.51cto.com/301216/67517

3、  container_of

位置:

用途:通过指向成员member的指针ptr,获取包含该成员的结构体type的指针

分析:

              #define container_of(ptr, type, member) ({                /

                     const typeof( ((type *)0)->member ) *__mptr = (ptr);       /

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

假设有结构体uio_mem

struct uio_mem

{

struct kobject kobj;

              unsigned long addr;

              unsigned long size;

              int memtype;

              void __iomem *internal_addr;

};

现有指向uio_mem的成员memtype的指针p(因此p的类型为int *),那么如何获取结构体uio_mem的指针?恭喜你,答对了,使用container_of(p, struct uio_mem, memtype)

将该宏展开为:

const typeof( ((struct uio_mem *)0)-> memtype) *__mptr = (p);// 1

(struct uio_mem *)( (char *)__mptr - offsetof(struct uio_mem, memtype) ); // 2

根据之前的分析,可以很容易理解语句1等价于:

const int *__mptr = p;

__mptr指向uio_mem的成员memtype,也即__mptruio_mem的成员memtype的地址。那么如果我们知道memtypestruct uio_mem中的偏移的话,用memtype的地址减去这个偏移不就知道结构体uio_mem的“首”地址了吗?

根据上述分析,通过offsetof(struct uio_mem, memtype)获取memtypestruct uio_mem中的偏移,然后再用memtype的实际地址(也即__mptr)减去这个偏移,这样就得到了结构体uio_mem的地址了,最后再将uio_mem的地址强制转换为struct uio_mem *,就获得了结构体uio_mem的指针了,这就是上述语句2所做的事情。很容易理解语句1等价于:

const int *__mptr = p;

__mptr指向uio_mem的成员memtype,也即__mptruio_mem的成员memtype的地址。那么如果我们知道memtypestruct uio_mem中的偏移的话,用memtype的地址减去这个偏移不就知道结构体uio_mem的“首”地址了吗?

根据上述分析,通过offsetof(struct uio_mem, memtype)获取memtypestruct uio_mem中的偏移,然后再用memtype的实际地址(也即__mptr)减去这个偏移,这样就得到了结构体uio_mem的地址了,最后再将uio_mem的地址强制转换为struct uio_mem *,就获得了结构体uio_mem的指针了,这就是上述语句2所做的事情。

阅读(1845) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~