kset_register

本文中的源码均来自linux内核3.14.3版本/lib/kobject.c文件

/**
 * kset_register - 初始化并添加一个kset
 * @k: kset.
 */
int kset_register(struct kset *k)
{
        int err;

        if (!k)
                return -EINVAL;

        kset_init(k);
        err = kobject_add_internal(&k->kobj);
        if (err)
                return err;
        kobject_uevent(&k->kobj, KOBJ_ADD);
        return 0;
}


/**
 * kset_init - 初始化一个kset
 * @k: kset
 */
void kset_init(struct kset *k)
{
        kobject_init_internal(&k->kobj);
        INIT_LIST_HEAD(&k->list);
        spin_lock_init(&k->list_lock);
}


static void kobject_init_internal(struct kobject *kobj)
{
        if (!kobj)
                return;
        kref_init(&kobj->kref);//kref是引用计数,该struct仅有一个成员,就是atomic_t refcount,这里把他初始化为1
        INIT_LIST_HEAD(&kobj->entry);//entry是一个struct list_head,这里把entry的next和prev均指向entry
        kobj->state_in_sysfs = 0; //不在sysfs中显示
        kobj->state_add_uevent_sent = 0;
        kobj->state_remove_uevent_sent = 0;
        kobj->state_initialized = 1;
}


static int kobject_add_internal(struct kobject *kobj)
{
        int error = 0;
        struct kobject *parent;

        if (!kobj)
                return -ENOENT;

        if (!kobj->name || !kobj->name[0]) {
                WARN(1, "kobject: (%p): attempted to be registered with empty name!\n", kobj);
                return -EINVAL;
        }

        parent = kobject_get(kobj->parent);//parent的引用计数加一

        /* join kset if set, use it as parent if we do not already have one */
/* 把kobject加入kset, 如果没有parent的话,就把它作为parent*/
        if (kobj->kset) {
                if (!parent)
                        parent = kobject_get(&kobj->kset->kobj);
                kobj_kset_join(kobj);
                kobj->parent = parent;
        }


        pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n", kobject_name(kobj), kobj, __func__, parent ? kobject_name(parent) : "", kobj->kset ?                                                               kobject_name(&kobj->kset->kobj) : "");

        error = create_dir(kobj);
        if (error) {
                kobj_kset_leave(kobj);
                kobject_put(parent);
                kobj->parent = NULL;

                /* be noisy on error issues */
                if (error == -EEXIST)
                        WARN(1, "%s failed for %s with -EEXIST, don't try to register things with "
            "the same name in the same directory.\n",__func__, kobject_name(kobj));
                else
                        WARN(1, "%s failed for %s (error: %d parent: %s)\n", __func__, kobject_name(kobj), error,
    parent ? kobject_name(parent) : "'none'");
        } else
                kobj->state_in_sysfs = 1;

        return error;
}

/**
 * kobject_get - object增加计数
 * @kobj: object.
 */
struct kobject *kobject_get(struct kobject *kobj)
{
        if (kobj)
                kref_get(&kobj->kref);
        return kobj;
}


我很想在这死磕一下,因为后面是继续调用原子操作来增加该计数,而我对原子操作只有概念上的认识,没有清晰的理解,不够看起来原子操作还挺麻烦的,这里就先放下了


static int create_dir(struct kobject *kobj)
{
        const struct kobj_ns_type_operations *ops;
        int error;

        error = sysfs_create_dir_ns(kobj, kobject_namespace(kobj));
        if (error)
                return error;

        error = populate_dir(kobj);
        if (error) {
                sysfs_remove_dir(kobj);
                return error;
        }

        /*
        * @kobj->sd 可能会被一个原始对象删除,保留一个备份索引
        * 保证它可以持续到@kobj 释放。
        */
        sysfs_get(kobj->sd);

        /*
        * 如果@kobj有ns_ops, 它的子对象需要用命名空间tags过滤,在@kobj->sd
        * 中使能命名空间支持。
        */
        ops = kobj_child_ns_ops(kobj);
        if (ops) {
                BUG_ON(ops->type <= KOBJ_NS_TYPE_NONE);
                BUG_ON(ops->type >= KOBJ_NS_TYPES);
                BUG_ON(!kobj_ns_type_registered(ops->type));

                kernfs_enable_ns(kobj->sd);
        }

        return 0;
}

你可能感兴趣的:(linux)