'why struct cdev has kobject member?

It's strange that struct cdev has struct kobject member, do any body knows the reason?



Solution 1:[1]

When kobjects are embedded inside other structures, the structures receive the standardized functions that a kobject provides. Most importantly, the structure's embedded kobject now enables the structure to become part of an object hierarchy. For example the cdev structure is presentable in an object hierarchy via the parent pointer cdev->kobj.parent and the list cdev->kobj.entry

Source: Linux Kernel Development by Robert Love

Solution 2:[2]

Sysfs is a Virtual filesystem that describes the devices available to the system in hierarchical pattern. This is done by using struct kobj.

struct kobject {
        char                    *k_name;
        char                    name[KOBJ_NAME_LEN];
        struct kref             kref;
        struct list_head        entry;
        struct kobject          *parent;
        struct kset             *kset;
        struct kobj_type        *ktype;
        struct dentry           *dentry;
};

For any driver kobj is required to export the device attributes to sysfs if we consider like i2c_client spi_device(spi client). we have kobj inside member struct dev to export the driver attributes to the user space virtual filesystem(Sysfs). The Kobj structure members handles all the operations including referring to the device numbers(major/minor) and file operations involved for open, read/write,close etc... of device.

In your case cdev_init & cdev_add will internally uses kobj to do the above operation.

Solution 3:[3]

There are two reasons:

  1. for reference counting, which is offered by kref internally.
static struct kobject *cdev_get(struct cdev *p)
{
    struct module *owner = p->owner;
    struct kobject *kobj;

    if (owner && !try_module_get(owner))
        return NULL;
    kobj = kobject_get_unless_zero(&p->kobj);
    if (!kobj)
        module_put(owner);
    return kobj;
}

void cdev_put(struct cdev *p)
{
    if (p) {
        struct module *owner = p->owner;
        kobject_put(&p->kobj);
        module_put(owner);
    }
}
  1. for release, that's also why kref is not enough(kref doesn't have a release hook).
static void cdev_default_release(struct kobject *kobj)
{
    struct cdev *p = container_of(kobj, struct cdev, kobj);
    struct kobject *parent = kobj->parent;

    cdev_purge(p);
    kobject_put(parent);
}

static void cdev_dynamic_release(struct kobject *kobj)
{
    struct cdev *p = container_of(kobj, struct cdev, kobj);
    struct kobject *parent = kobj->parent;

    cdev_purge(p);
    kfree(p);
    kobject_put(parent);
}

static struct kobj_type ktype_cdev_default = {
    .release    = cdev_default_release,
};

static struct kobj_type ktype_cdev_dynamic = {
    .release    = cdev_dynamic_release,
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 microMolvi
Solution 2 kzs
Solution 3