嵌入式技术
今天在看平台设备实现的时候,看到to_xxx开头的“函数”。包括在内核中也有很多此类的“函数”,其实他们都是container_of的宏。因为内核是链表和结构体的世界,因此内核中有大量需求要 根据结构体成员获取结构体地址 ,或者根据结构体类型和结构体成员类型获取成员在结构体的偏移
match函数
最后container_of的实现如下:
根据注释可以得到几点信息:container_of的作用是根据结构体成员地址找结构体地址
ptr是指向成员的指针
type是结构体的类型
member是成员的名字
下面来分析一下这到底如何实现。
const typeof( ((type *)0)->member ) *__mptr = (ptr);
这句话实际上仅仅是把ptr的地址传给一个临时的变量__mptr。const表明__mptr不会修改ptr指向的数据,具体就是结构体成员的数据。typeof是扩展关键字,用于获取某个变量的类型,确保menber的类型和传入的ptr指向的数据类型一致。
接下来的重点就是:
((type *)0)->member如何理解?
先来概括一下:用一个指向0地址的指针,获取结构体的成员变量。
看看平时是如何获取一个结构体变量的,首先初始化一个结构体实例a,然后声明一个结构体指针指向这个实例:struct xxx *p = &a;此时 p = a的地址,等价于 (struct xxx *)&a;
再看看(type *)0是不是很像?type就是结构体的类型,0就是某个结构体实例的地址。就是把结构体实例放到0地址嘛!((type *)0)等价于一个指针,这个指针指向0地址,类型是type类型。接下来都水到渠成。
总结一下:const typeof( ((type *)0)->member ) *__mptr = (ptr);仅仅是把传入的ptr地址赋给_mptr临时变量,得到的_mptr是一个绝对地址。假设是20,后面会用到。
(type *)( (char *)__mptr - offsetof(type,member) );})
先看offsetof(type,member) )的实现
offsetof
这里和上面分析的一样,只不过多了一个取地址符号:把结构体实例放到0地址,然后获取成员变量,然后取地址,这时候取出的地址是相对0偏移的地址,也是相对于结构体地址的偏移地址,假设是4.
那么__mptr - offsetof = 20 - 4 = 16 = 结构体地址(绝对地址)。
理解了这个,其他都是一些类型检查,边角料。
全部0条评论
快来发表一下你的评论吧 !