为什么说设备的引用计数为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); } ... }
相关文章推荐
- 使用内部类写工厂方法
- MySQL 分区表脚本
- Spring <context:annotation-config/> 解说
- Profiler
- Oracle统计信息
- 转:ios的图片文件上传代码
- servlet学习笔记02 servlet类、对象
- 插件uaredirect.js实现电脑版跳转到手机版网站
- DNS基础及域名系统架构
- iOS 绘制虚线
- 详解JavaScript基于面向对象之创建对象(1)
- mybatis映射文件语法
- 如何在windows64位的系统上安装,配置mysql?
- js 数组取出最大值最小值的2种方法
- win8.1开机出现OneDrive服务现在不可用该怎么办?
- 二维数组和指针(C语言)
- 网络通信原理
- Majority Element
- 数据持久化
- UVA 624(01背包记录路径)