分类: LINUX
2008-07-20 11:18:53
/**
* 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 (, , ) ({ \
const ( (( *)0)-> ) * = (); \
( *)( (char *) - (,) );})
指针ptr指向结构体type中的成员member;通过指针ptr,返回结构体type的起始地址。
type
|----------|
| |
| |
|----------|
ptr-->| member --|
|----------|
| |
| |
|----------|
那么具体看一个它的应用。从宏观的效果来看,container_of的确是取得了ptr所在结构,那么它是如何实现的?
在/linux/lib/kobject.c中kobject_release被定义如下
static void (struct *)
{
((, struct , ));
}
它的作用是kobject清除函数。当其引用计数为0时,释放对象占用的资源。
它的实现中就用到了container_of。它的参数是kref为struct kref类型,而
kobject_cleanup的定义为:
void (struct * ) //在/linux/lib/kobject.c
中,它的参数为struct kobject *类型,而struct kobject结构中就包含struct
kref 类型的成员:linux/include/linux/kobject.h
59/* The list of strings defining the valid kobject actions as specified above */
60extern const char *kobject_actions[];
61
62
63struct kobject {
64 const char * k_name;
65 char name[KOBJ_NAME_LEN];
66 struct kref kref;
67 struct list_head entry;
68 struct kobject * parent;
69 struct kset * kset;
70 struct kobj_type * ktype;
71 struct dentry * dentry;
72};
#define (, , ) ({ \
const ( (( *)0)-> ) * = (); \
( *)( (char *) - (,) );})
此处ptr就是kobject_release的参数kref,type就是struct kobject,member就是
struct kobject结构中的成员kref,那么替换之后就为:
container_of(para_kref,struct kobject,kref) //次处由于ptr和member的名字
都为kref,但是不一样的,所以使用para_kref代替kobject_release的参数kref,
({
const typeof(((struct kobject*)0)->kref) *__mptr = (para_ptr);
(struct kobject *)((char *)__mptr - offsetof(struct kobject,kref));
})
((struct kobject *)0)->kref是取得kobject结构的kref成员,在使用typeof作用于它就取
得了kref成员的类型,即struct kref,到此整体的第一行可翻译为:
const struct kref *__mptr=(para_ptr);
offsetof(struct kobject,kref)是取得kref成员在struct kobject结构中的偏移
,我编写了一个内核模块测试的结果为24, 所以第二行可以翻译为:
(struct kobject *)((char *)__mptr-24);
这样就取得了para_ptr所在的指向struct kobject的地址,在使用(struct kobject *)将其强制转化成指向struct kobject结
构的指针,到此实现了上面所说的container_of的功能。