快乐虾
http://blog.csdn.net/lights_joy/
本文适用于
ADSP-BF561
uclinux-2008r1.5-rc3 (smp patch)
欢迎转载,但请保留作者信息
内核中大量使用container_of这个宏,用以进行数据结构的向上转换,比如这样一段代码:
static int platform_match(struct device * dev, struct device_driver * drv)
{
struct platform_device *pdev = container_of(dev, struct platform_device, dev);
return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
}
在这里struct platform_device定义为:
struct platform_device {
const char * name;
u32 id;
struct device dev;
u32 num_resources;
struct resource * resource;
};
注意,在这个结构体里面包含了一个叫device的结构体,可以将struct platform_device称为父结构体,将struct device称为子结构体。
在上述函数中,传递进来的dev指针将指向platform_device这个父结构体中的dev成员,而contianer_of这个宏的作用则在于通过这个结构体成员的指针获得其父结构体的指针,在这里就是platform_device这一结构体的指针。
要达到这一目的很容易,只要将这个成员的指针减去此成员在整个结构体内的偏移量自然就可以了。看看container_of的定义:
/**
* 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) );})
这个宏定义的第一行构建一个叫__mptr的临时变量,实际上并不是必须的,它的作用只是强制编译器对数据类型进行检查。第二行里面的__mptr实际就是子结构体成员的指针。
偏移量的计算由offsetof宏完成:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
这种方法到处都在用,没什么新奇的。