• kobject_create_and_add


    本文源代码均来自linux 3.14.3版本号/lib/kobject.c文件

    /**
     * kobject_create_and_add - 动态创建一个kobject结构并注冊到sysfs
     *
     * @name: kobject的名称
     * @parent: kobject的parent kobject of this kobject, 假设有的话
     *
     * 该方法动态创建一个kobject结构并注冊到sysfs。

    当你完毕该结构
     * 之后. 调用kobject_put()。这样该结构在不再使用时将会动态的释放。


     *
     * 假设该kobject无法被创建,将会返回NULL。
     */
    struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
    {
            struct kobject *kobj;
            int retval;

            kobj = kobject_create();
            if (!kobj)
                    return NULL;

            retval = kobject_add(kobj, parent, "%s", name);
            if (retval) {
                    printk(KERN_WARNING "%s: kobject_add error: %d ",  __func__, retval);
                    kobject_put(kobj);
                    kobj = NULL;
            }
            return kobj;
    }


    /**
     * kobject_create - 动态创建一个kobject结构
     *
     * 动态创建一个kobject结构,并将其设置为一个带默认释放方法的
     * 动态的kobject。
     *
     * 假设无法创建kobject。将会返回NULL。

    从这里返回的kobject 结构释放
     * 必须调用kobject_put() 方法而不是kfree()。由于kobject_init()已经被调用
     * 过了。
     */
    struct kobject *kobject_create(void)
    {
            struct kobject *kobj;

            kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
            if (!kobj)
                    return NULL;

            kobject_init(kobj, &dynamic_kobj_ktype);
            return kobj;
    }


    /**
     * kobject_init - 初始化一个kobject结构
     * @kobj: 指向要初始化的kobject的指针
     * @ktype: 指向该kobject 的ktype的指针
     *
     * 该方法会正确的初始化一个kobject来保证它能够被传递给kobject_add()
     * 调用.
     *
     * 该功能被调用后,kobject必须通过调用kobject_put()来清理,而不是直接
     * 调用kfree,来保证全部的内存都能够被正确的清理。
     */
    void kobject_init(struct kobject *kobj, struct kobj_type *ktype)
    {
            char *err_str;

            if (!kobj) {
                    err_str = "invalid kobject pointer!";
                    goto error;
            }
            if (!ktype) {
                    err_str = "must have a ktype to be initialized properly! ";
                    goto error;
            }
            if (kobj->state_initialized) {
                    /* do not error out as sometimes we can recover */
                    printk(KERN_ERR "kobject (%p): tried to init an initialized object, something is seriously wrong. ", kobj);
                    dump_stack();
    }

            kobject_init_internal(kobj);
            kobj->ktype = ktype;
            return;

    error:
            printk(KERN_ERR "kobject (%p): %s ", kobj, err_str);
            dump_stack();
    }


    static void kobject_init_internal(struct kobject *kobj)
    {
            if (!kobj)
                    return;
            kref_init(&kobj->kref);
            INIT_LIST_HEAD(&kobj->entry);
            kobj->state_in_sysfs = 0;
            kobj->state_add_uevent_sent = 0;
            kobj->state_remove_uevent_sent = 0;
            kobj->state_initialized = 1;
    }


    /**
     * kobject_add - kobject加入主方法
     * @kobj: 要加入的kobject
     * @parent: 指向父kobject的指针
     * @fmt: kobject带的名称格式
     *
     * 本方法中会设置kobject名称并加入到kobject阶层。
     *
     * 假设设置了@parent, 那么@kobj的parent将会被设置为它.
     * 假设 @parent为空, 那么该@kobj的 parent会被设置为与该kobject
     * 相关联的.  假设没有kset分配给这个kobject。那么该kobject会放在
     * sysfs的根文件夹。
     *
     * 假设该方法返回错误。必须调用 kobject_put()来正确的清理该object
     * 相关联的内存。
     * 在不论什么情况下都不要直接通过调用to kfree()来直接释放传递给该方法
     * 的kobject,那样会导致内存泄露。
     *
     * 注意。该调用不会创建"add" uevent, 调用方须要为该object设置好全部
     * 必要的sysfs文件,然后再调用带UEVENT_ADD 參数的kobject_uevent() 
     * 来保证用户控件能够正确的收到该kobject创建的通知。
     */
    int kobject_add(struct kobject *kobj, struct kobject *parent,
    const char *fmt, ...)
    {
            va_list args;
            int retval;

            if (!kobj)
                    return -EINVAL;

            if (!kobj->state_initialized) {
                    printk(KERN_ERR "kobject '%s' (%p): tried to add an "
                          "uninitialized object, something is seriously wrong. ",
                    kobject_name(kobj), kobj);
                    dump_stack();
                    return -EINVAL;
            }
            va_start(args, fmt);
            retval = kobject_add_varg(kobj, parent, fmt, args);
            va_end(args);

            return retval;
    }


    static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,
       const char *fmt, va_list vargs)
    {
            int retval;

            retval = kobject_set_name_vargs(kobj, fmt, vargs);
            if (retval) {
                    printk(KERN_ERR "kobject: can not set name properly! ");
                    return retval;
    }
            kobj->parent = parent;
            return kobject_add_internal(kobj);
    }


    /**
     * kobject_set_name_vargs - 设置一个kobject的名称
     * @kobj: 要设置名称的kobject
     * @fmt: 用来构建名称的字符串格式
     * @vargs: 构建字符串的參数
     */
    int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
     va_list vargs)
    {
            const char *old_name = kobj->name;
            char *s;

            if (kobj->name && !fmt)
                    return 0;

            kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs);
            if (!kobj->name) {
                    kobj->name = old_name;
                    return -ENOMEM;
            }


            /* ewww... some of these buggers have '/' in the name ... */
            while ((s = strchr(kobj->name, '/')))
                    s[0] = '!';

            kfree(old_name);
            return 0;
    }


    kobject_add_internal源代码前面已经粘贴过了。这里就不再继续粘贴了

  • 相关阅读:
    线性代数回顾+深化(未完成版)
    HIT OS2020 Spring Lab2
    选择
    工业互联网
    leetcode-200 岛屿数量
    记网易面试题<二>
    记网易面试题《一》
    leetecode-14-最长公共子串-简单
    leetcode-1012 至少有1位重复的数字
    协程
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/6758580.html
Copyright © 2020-2023  润新知