设备模型object

Linux内核修炼之kobject,ktype,kset,subsys关系  

linux设备模型

sysfs

引用计数

一 device_register()

int device_register(struct device *dev)
{
	device_initialize(dev);
	return device_add(dev);
}

1 device_initialize(dev)

device_initialize()->kobject_init()->kobject_init_internal()->kref_init()->
static inline void kref_init(struct kref *kref)
{
	atomic_set(&kref->refcount, 1);//引用计数refcount初始化为1,
}

2 device_add(dev)

device_add()->kobject_add()->kobject_add_varg()->kobject_add_internal()->
parent = kobject_get(kobj->parent);
struct kobject *kobject_get(struct kobject *kobj)
{
	if (kobj)
		kref_get(&kobj->kref);
	return kobj;
}  
static inline void kref_get(struct kref *kref)
{
	/* If refcount was 0 before incrementing then we have a race
	 * condition when this kref is freeing by some other thread right now.
	 * In this case one should use kref_get_unless_zero()
	 */
	WARN_ON_ONCE(atomic_inc_return(&kref->refcount) < 2);
}
其parent的引用计数加1,此时应该>=2。

二 device_unregister()

void device_unregister(struct device *dev)
{
	pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
	device_del(dev);
	put_device(dev);
}

1 device_del(dev)

device_del()->kobject_del(kobj->parent)->kobject_put()->kref_put()->kref_sub()->
static inline int kref_sub(struct kref *kref, unsigned int count,
	     void (*release)(struct kref *kref))
{
	WARN_ON(release == NULL);

	if (atomic_sub_and_test((int) count, &kref->refcount)) {
		release(kref);
		return 1;
	}
	return 0;
}
其parent的引用计数减1,如果计数为0执行release(),即kobject_release(),对其parent进行release()。

2 put_device(dev)

put_device()->kobject_put(&dev->kobj)->kref_sub()->
引用计数减1,如果计数为0执行release(),即kobject_release();对自己进行release()。

kobject_release()->kobject_cleanup()->(t->release(kobj))
t->release(kobj)就是device_initialize(struct device *dev)->kobject_init(&dev->kobj, &device_ktype)中初始化的device_release:
static struct kobj_type device_ktype = {
	.release	= device_release,
	.sysfs_ops	= &dev_sysfs_ops,
	.namespace	= device_namespace,
};
static void device_release(struct kobject *kobj)
{
	struct device *dev = kobj_to_dev(kobj);
	struct device_private *p = dev->p;

	/*
	 * Some platform devices are driven without driver attached
	 * and managed resources may have been acquired.  Make sure
	 * all resources are released.
	 *
	 * Drivers still can add resources into device after device
	 * is deleted but alive, so release devres here to avoid
	 * possible memory leak.
	 */
	devres_release_all(dev);

	if (dev->release)
		dev->release(dev);
	else if (dev->type && dev->type->release)
		dev->type->release(dev);
	else if (dev->class && dev->class->dev_release)
		dev->class->dev_release(dev);
	else
		WARN(1, KERN_ERR "Device '%s' does not have a release() "
			"function, it is broken and must be fixed.\n",
			dev_name(dev));
	kfree(p);
}
此时会执行dev->release(dev)。

你可能感兴趣的:(设备模型object)