linux设备模型
sysfs
int device_register(struct device *dev) { device_initialize(dev); return device_add(dev); }
static inline void kref_init(struct kref *kref) { atomic_set(&kref->refcount, 1);//引用计数refcount初始化为1, }
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。
void device_unregister(struct device *dev) { pr_debug("device: '%s': %s\n", dev_name(dev), __func__); device_del(dev); put_device(dev); }
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()。
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)。