您的位置:首页 > 其它

为什么说设备的引用计数为0时,系统会自动调用它的release函数

2015-12-10 10:59 676 查看
调用顺序:

/**
在前面的博文“kobject浅析”中,我们知道设备的引用计数是由 嵌套在kobject中的struct kref来决定的
struct kref {
atomic_t refcount;//当它的值为0的时候,kobject的生命周期就结束了,release会被调用
};
*/
static struct ploatform_device cty_dev = {
.name = "leesagacious",
.resources = cty_resource,
.num_resources = ARRAY_SIZE(cty_resource),
.id = -1,
.dev = { //release函数,当设备的引用计数为0的时候,由内核自动调用,如果不提供这个函数,会报错
.release = cty_release,
}
};

/**
卸载平台设备
*/
void platform_device_unregister(struct platform_device *pdev)
{
//移除平台设备,这个函数将会释放设备占用的所有的内存、端口、irq...资源
platform_device_del(pdev);
/**
下面看这个函数
*/
platform_device_put(pdev);
}
void platform_device_put(struct platform_device *pdev)
{
if (pdev)
{
/**
减少设备的引用计数
*/
put_device(&pdev->dev);
}
}

void kobject_put(struct kobject *kobj)
{
if (kobj) {
/**
如果kobject还没有被初始化。请见前面的“kobject浅析”博文
*/
if (!kobj->state_initialized)
{
WARN(1, KERN_WARNING "kobject: '%s' (%p): is not "
"initialized, yet kobject_put() is being "
"called.\n", kobject_name(kobj), kobj);
}
/**
减少设备的引用计数,如果为0,kobject_release函数将会被调用
*/
kref_put(&kobj->kref, kobject_release);
}
}

int kref_put(struct kref *kref, void (*release)(struct kref *kref))
{
WARN_ON(release == NULL);
WARN_ON(release == (void (*)(struct kref *))kfree);
/**
从原子变量refcount中减去 1 ,如果refcount为0,返回true,就调用release函数
这个release函数,就是kobject_put中的kobject_release()函数
*/
if (atomic_dec_and_test(&kref->refcount)) {
/**
调用kobject_release()函数
*/
release(kref);
return 1;
}
return 0;
}

/**
当设备的引用计数为0的时候,自动被调用的release函数
*/
static void kobject_release(struct kref *kref)
{
/**
释放kobject占用的资源
*/
kobject_cleanup(container_of(kref, struct kobject, kref));
}

static void kobject_cleanup(struct kobject *kobj)
{
/**
获取 kobject的属性
static inline struct kobj_type *get_ktype(struct kobject *kobj)
{
return kobj->ktype;
}
kobject与kobj_type的关联是再kobject_init()函数中设置的
*/
struct kobj_type *t = get_ktype(kobj);
....
/**
如果没有提供release函数,则报错
*/
if (t && !t->release)
{
pr_debug("kobject: '%s' (%p): does not have a release() "
"function, it is broken and must be fixed.\n",
kobject_name(kobj), kobj);
}
/**
如果提供了release函数,那么就调用它
*/
if (t && t->release) {
pr_debug("kobject: '%s' (%p): calling ktype release\n",kobject_name(kobj), kobj);
t->release(kobj);
}
...
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: