嵌入式软件开发之------浅析linux设备驱动模型(一)kobject和kset

2019-07-12 23:08发布

  Linux代码版本:linux3.0 开发板环境: tiny4412 导读:说起linux设备驱动,很容易想到一切皆文件的思想、bus、device、driver还有sysfs文件系统。说起总线又很容易想到platform、I2c、USB等等,device和driver都挂接在一种总线上,然后通过xxx_match函数进行匹配,各种书籍资料也更多的是介绍如果调用接口进行驱动开发,却很少谈及注册一个设备和驱动的时候都发生了什么,驱动和设备是如何匹配的,sys下的目录和文件是如何产生的。如果不去理解驱动内部的机制,那么就只能开发过一种驱动学会一种驱动框架,而这种积累方式未免会显得低效,时间长了不用还容易忘。当了解驱动模型的内部机制后,就会发现各种类型的驱动框架有很大相似性,即使要开发一种新的硬件的驱动,看一下代码很快就知道框架是怎样的。  

一、kobjectkset

    俗话说万丈高楼平地起,再高的大楼也是由砖和钢筋等基本材料堆积起来的,同样linux驱动模型也有自己的基本材料,那就是kobject和kset。sys下的每一个目录,都对应一个kobject,sys下的目录层次结构,其实也就是kobject的层次结构。而kset则是kobject的集合。 下面先看kobject和kset的结构体 struct kobject {     const char *name;     struct list_head entry;     struct kobject *parent;     struct kset *kset;     struct kobj_type *ktype;     struct sysfs_dirent *sd;     struct kref kref;     unsigned int state_initialized:1;     unsigned int state_in_sysfs:1;     unsigned int state_add_uevent_sent:1;     unsigned int state_remove_uevent_sent:1;     unsigned int uevent_suppress:1; };   const char *name:   kobject 名称,当包含此kobject的内核对象被加入内核时,那么将会以这个name在sys建立一个目录。 struct list_head entry: 用于将一系列内核对象构成链表 struct kobject *parent: 指该kobject的上一层节点,在sys表现为上一层目录,用于表现层次关系 struct kset *kset: 前面说kset是一系列kobject的集合,该成员指向所属的kset struct kobj_type *ktype: 该kobject对象的类型,不同的内核对象类型有不同的属性和操作函数如下面的device_type和kset_type,具体用途后面用到的时候再详说。 static struct kobj_type device_ktype = { .release = device_release, .sysfs_ops = &dev_sysfs_ops, .namespace = device_namespace, }; static struct kobj_type kset_ktype = { .sysfs_ops = &kobj_sysfs_ops, .release = kset_release, }; struct sysfs_dirent *sd: 该kobject在sysfs中对应的目录目录实例 unsigned int state_initialized: 表示该内核对象是否初始化过,表示已经初始化,表示未初始化 unsigned int state_in_sysfs: 表示该kobject所代表的内核对象是否在sys中是否建立的目录 unsigned int state_add_uevent_sent: unsigned int state_remove_uevent_sent add和让remove事件的标志位 unsigned int uevent_suppress: 该kobject对象发生变化时,将会导致该对象所属的kset向用户空间发送event消息,uevent_suppress是用来表明当kobject状态发生变化时,是否允许ket向用户空间发送event消息。0表示允许,1表示不允许。 一般应用都是将kobject嵌入对象中,单独说kobject每个成员也很难理解,当kobject成员被使用时就容易理解其用途。其实kset也是一个嵌入了kobject的内核对象,是一个很好的例子。 struct kset { struct list_head list; spinlock_t list_lock; struct kobject kobj; const struct kset_uevent_ops *uevent_ops; }; struct list_head list: 前面说了kset就是 kobject的集合,此成员就是要将kobject串起来(还记得kobject中的entry成员吗) spinlock_t list_lock: 自旋锁,用来进行互斥访问 struct kobject kobj: kset也是封装了kobject const struct kset_uevent_ops *uevent_ops 当kset中的某些kobject成员状态发生变化需要通知用户空间时,调用其中的函数 struct kset_uevent_ops { int (* const filter)(struct kset *kset, struct kobject *kobj); const char *(* const name)(struct kset *kset, struct kobject *kobj); int (* const uevent)(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env); };   这三个函数将会在kobject_uevent中调用到,后面具体实例再分析。  

二、ksetkobject实例

    一块砖,怎么看也很难想象出来和高楼大厦有啥关系,可当你看着工人一块一块用起来就知道它的作用。对于kobject和kset做再详细的说明,也很难理解,当我们看到他们的每个成员在代码中的应用时,自然很容易理解其用途,所以对于kobject和kset结构体就知道它有些什么进行了,具体用途在代码中进行理解。 很多资料都会说sysfs是用户和内核空间的交互接口,kobject对应sys的一个目录(kset也是封装了一个kobject,kset对应的目录还是通过kobect实现),下面就看一下kset和kobject究竟是怎么对应的sys下的目录的。 先看下sys下的几个目录 [root@FriendlyARM /sys]# ls block class devices fs module bus dev firmware kernel power 下面是 创建这些目录的函数: block: sys目录下创建bolck目录 static int __init genhd_device_init(void) {     ......     block_depr = kobject_create_and_add("block", NULL);     ...... }   class:   sys目录下创建class目录 int __init classes_init(void) {     ......     class_kset = kset_create_and_add("class", NULL, NULL);     ...... }   devices 和dev:   在sys下创建了devices 和dev 目录,又在dev目录下创建了block和char两个目录 int __init devices_init(void) {     ......     devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);     ......     dev_kobj = kobject_create_and_add("dev", NULL);     sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);     sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); }   fs:   sys目录下创建fs目录 void __init mnt_init(void) {     ......     fs_kobj = kobject_create_and_add("fs", NULL);     ...... } module: 在sys目录下创建module目录 static int __init param_sysfs_init(void) {     ......     module_kset = kset_create_and_add("module",     &module_uevent_ops, NULL);     ...... }   bus   在sys目录下创建bus目录 int __init buses_init(void) {     ......     bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);     ...... } firmware: sys目录下创建firmware目录 int __init firmware_init(void) {     ......     firmware_kobj = kobject_create_and_add("firmware", NULL);     ...... } kernel: sys目录下创建kernel目录 static int __init ksysfs_init(void) {     ......     kernel_kobj = kobject_create_and_add("kernel", NULL);     ...... }   power:   sys目录下创建power目录 static int __init pm_init(void) {     ......     power_kobj = kobject_create_and_add("power", NULL);     ...... }      从函数名字上也可以看出,class、devices、module和bus为kset,其它的为kobject。接下来先解析kset_create_and_add,第一个参数为name,第二个为kset_uevent_ops,第三个为parent_kobj,注意当parent_kobj为NULL时,则是在sys创建目录,后面从代码上看到;   struct kset *kset_create_and_add(const char *name, const struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) { struct kset *kset; int error; /*创建一个kset并初始化*/ kset = kset_create(name, uevent_ops, parent_kobj); if (!kset) return NULL; error = kset_register(kset); if (error) { kfree(kset); return NULL; } return kset; }   接下来看一下几个kset的kset_uevent_ops,class的为NULL,device_uevent_ops为device_uevent_ops,module的为module_uevent_ops,bus的为bus_uevent_ops   static const struct kset_uevent_ops device_uevent_ops = { .filter = dev_uevent_filter, .name = dev_uevent_name, .uevent = dev_uevent, }; static const struct kset_uevent_ops module_uevent_ops = { .filter = uevent_filter, }; static const struct kset_uevent_ops bus_uevent_ops = { .filter = bus_uevent_filter, }; 再看filter成员 static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) { struct kobj_type *ktype = get_ktype(kobj); /*先判断是该kobject是不是device_type类型,再判断是否挂接在某个bus上或者是否属某个class*/ if (ktype == &device_ktype) { struct device *dev = to_dev(kobj); if (dev->bus) return 1; if (dev->class) return 1; } return 0; } static int uevent_filter(struct kset *kset, struct kobject *kobj) { struct kobj_type *ktype = get_ktype(kobj); /* 判断该kobject是否为module_ktype类型*/ if (ktype == &module_ktype) return 1; return 0; } static int bus_uevent_filter(struct kset *kset, struct kobject *kobj) { struct kobj_type *ktype = get_ktype(kobj); /* 判断该kobject是否为bus_ktype类型*/ if (ktype == &bus_ktype) return 1; return 0; } filter 的作用就是检查某些条件,除了devices的要求kobject的type,挂接在某个bus或某个class上,其它两个都只检查kobject的type,符合要求才允许上报。 再看dev_uevent_name,就是返回所指向bus或class的name devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); struct kset *kset_create_and_add(const char *name, const struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) { struct kset *kset; int error;         /*创建一个kset*/ kset = kset_create(name, uevent_ops, parent_kobj); { struct kset *kset; int retval; /*先为kset申请内存*/ kset = kzalloc(sizeof(*kset), GFP_KERNEL); if (!kset) return NULL; /*设置kobject名字,kset->kobj->name = “devices”*/ retval = kobject_set_name(&kset->kobj, name); if (retval) { kfree(kset); return NULL; } /*kset->uevent_ops = device_uevent_ops*/ kset->uevent_ops = uevent_ops; /*kset->kobj.parent = NULL*/ kset->kobj.parent = parent_kobj; /* * The kobject of this kset will have a type of kset_ktype and belong to * no kset itself. That way we can properly free it when it is * finished being used. */ kset->kobj.ktype = &kset_ktype; kset->kobj.kset = NULL; return kset; } if (!kset) return NULL; /*注册kset*/ error = kset_register(kset); { int err; if (!k) return -EINVAL; /*初始化kset*/ kset_init(k); { kobject_init_internal(&k->kobj); { if (!kobj) return; /*引用计数初始化为1*/ kref_init(&kobj->kref); /*list初始化*/ INIT_LIST_HEAD(&kobj->entry); /*还未在sysfs中创建目录*/ kobj->state_in_sysfs = 0; kobj->state_add_uevent_sent = 0; kobj->state_remove_uevent_sent = 0; /*已经初始化*/ kobj->state_initialized = 1; } INIT_LIST_HEAD(&k->list); spin_lock_init(&k->list_lock); } err = kobject_add_internal(&k->kobj); { int error = 0; struct kobject *parent; if (!kobj) return -ENOENT; /*初始化时设置为 kobj->name = “devices”*/ if (!kobj->name || !kobj->name[0]) { WARN(1, "kobject: (%p): attempted to be registered with empty " "name! ", kobj); return -EINVAL; } /*获取kobj的parent,前面初始化时设置为kset->kobj.parent = NULL*/ parent = kobject_get(kobj->parent); /* join kset if set, use it as parent if we do not already have one */ /* 前面初始设置为kset->kobj.kset = NULL */ if (kobj->kset) { if (!parent) /*如果kobj有kset但没有parent,则将kset所谓parent*/ parent = kobject_get(&kobj->kset->kobj); /*将kobj键入kset->list中*/ kobj_kset_join(kobj); { if (!kobj->kset) return; kset_get(kobj->kset); spin_lock(&kobj->kset->list_lock); list_add_tail(&kobj->entry, &kobj->kset->list); spin_unlock(&kobj->kset->list_lock); } kobj->parent = parent; } pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s' ", kobject_name(kobj), kobj, __func__, parent ? kobject_name(parent) : "", kobj->kset ? kobject_name(&kobj->kset->kobj) : ""); /*在sys下创建devices目录*/ error = create_dir(kobj); if (error) { kobj_kset_leave(kobj); kobject_put(parent); kobj->parent = NULL; /* be noisy on error issues */ if (error == -EEXIST) printk(KERN_ERR "%s failed for %s with " "-EEXIST, don't try to register things with " "the same name in the same directory. ", __func__, kobject_name(kobj)); else printk(KERN_ERR "%s failed for %s (%d) ", __func__, kobject_name(kobj), error); dump_stack(); } else /*已在sys创建devices目录,将标记置1*/ kobj->state_in_sysfs = 1; return error; } if (err) return err; kobject_uevent(&k->kobj, KOBJ_ADD); { return kobject_uevent_env(kobj, action, NULL); { struct kobj_uevent_env *env; const char *action_string = kobject_actions[action]; const char *devpath = NULL; const char *subsystem; struct kobject *top_kobj; struct kset *kset; const struct kset_uevent_ops *uevent_ops; int i = 0; int retval = 0; #ifdef CONFIG_NET struct uevent_sock *ue_sk; #endif pr_debug("kobject: '%s' (%p): %s ", kobject_name(kobj), kobj, __func__); /* search the kset we belong to */ /*查找kobj所属的kset,看前面kset->kobj.kset = NULL,kset->kobj->parent = NULL*/ top_kobj = kobj; while (!top_kobj->kset && top_kobj->parent) top_kobj = top_kobj->parent; if (!top_kobj->kset) { pr_debug("kobject: '%s' (%p): %s: attempted to send uevent " "without kset! ", kobject_name(kobj), kobj, __func__); return -EINVAL; } /*kset = NULL*/ kset = top_kobj->kset; uevent_ops = kset->uevent_ops; /* skip the event, if uevent_suppress is set*/ /*如果被置1,不报uevent,看前面的代码,此位并没有被置位*/ if (kobj->uevent_suppress) { pr_debug("kobject: '%s' (%p): %s: uevent_suppress " "caused the event to drop! ", kobject_name(kobj), kobj, __func__); return 0; } /* skip the event, if the filter returns zero. */ /*kset->uevent_ops在此有用了,但kset->kobj.kset = NULL ,函数在此返回*/ if (uevent_ops && uevent_ops->filter) if (!uevent_ops->filter(kset, kobj)) { pr_debug("kobject: '%s' (%p): %s: filter function " "caused the event to drop! ", kobject_name(kobj), kobj, __func__); return 0; } /*下面的代码将在以后能执行至此的实例中分析*/ /* originating subsystem */ ............ } return 0; } if (error) { kfree(kset); return NULL; } return kset; }/*创建一个kset*/ kset = kset_create(name, uevent_ops, parent_kobj); { struct kset *kset; int retval; /*先为kset申请内存*/ kset = kzalloc(sizeof(*kset), GFP_KERNEL); if (!kset) return NULL; /*设置kobject名字,kset->kobj->name = “devices”*/ retval = kobject_set_name(&kset->kobj, name); if (retval) { kfree(kset); return NULL; } /*kset->uevent_ops = device_uevent_ops*/ kset->uevent_ops = uevent_ops; /*kset->kobj.parent = NULL*/ kset->kobj.parent = parent_kobj; /* * The kobject of this kset will have a type of kset_ktype and belong to * no kset itself. That way we can properly free it when it is * finished being used. */ kset->kobj.ktype = &kset_ktype; kset->kobj.kset = NULL; return kset; } if (!kset) return NULL; /*注册kset*/ error = kset_register(kset); { int err; if (!k) return -EINVAL; /*初始化kset*/ kset_init(k); { kobject_init_internal(&k->kobj); { if (!kobj) return; /*引用计数初始化为1*/ kref_init(&kobj->kref); /*list初始化*/ INIT_LIST_HEAD(&kobj->entry); /*还未在sysfs中创建目录*/ kobj->state_in_sysfs = 0; kobj->state_add_uevent_sent = 0; kobj->state_remove_uevent_sent = 0; /*已经初始化*/ kobj->state_initialized = 1; } INIT_LIST_HEAD(&k->list); spin_lock_init(&k->list_lock); } err = kobject_add_internal(&k->kobj); { int error = 0; struct kobject *parent; if (!kobj) return -ENOENT; /*初始化时设置为 kobj->name = “devices”*/ if (!kobj->name || !kobj->name[0]) { WARN(1, "kobject: (%p): attempted to be registered with empty " "name! ", kobj); return -EINVAL; } /*获取kobj的parent,前面初始化时设置为kset->kobj.parent = NULL*/ parent = kobject_get(kobj->parent); /* join kset if set, use it as parent if we do not already have one */ /* 前面初始设置为kset->kobj.kset = NULL */ if (kobj->kset) { if (!parent) /*如果kobj有kset但没有parent,则将kset所谓parent*/ parent = kobject_get(&kobj->kset->kobj); /*将kobj键入kset->list中*/ kobj_kset_join(kobj); { if (!kobj->kset) return; kset_get(kobj->kset); spin_lock(&kobj->kset->list_lock); list_add_tail(&kobj->entry, &kobj->kset->list); spin_unlock(&kobj->kset->list_lock); } kobj->parent = parent; } pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s' ", kobject_name(kobj), kobj, __func__, parent ? kobject_name(parent) : "", kobj->kset ? kobject_name(&kobj->kset->kobj) : ""); /*在sys下创建devices目录*/ error = create_dir(kobj); if (error) { kobj_kset_leave(kobj); kobject_put(parent); kobj->parent = NULL; /* be noisy on error issues */ if (error == -EEXIST) printk(KERN_ERR "%s failed for %s with " "-EEXIST, don't try to register things with " "the same name in the same directory. ", __func__, kobject_name(kobj)); else printk(KERN_ERR "%s failed for %s (%d) ", __func__, kobject_name(kobj), error); dump_stack(); } else /*已在sys创建devices目录,将标记置1*/ kobj->state_in_sysfs = 1; return error; } if (err) return err; kobject_uevent(&k->kobj, KOBJ_ADD); { return kobject_uevent_env(kobj, action, NULL); { struct kobj_uevent_env *env; const char *action_string = kobject_actions[action]; const char *devpath = NULL; const char *subsystem; struct kobject *top_kobj; struct kset *kset; const struct kset_uevent_ops *uevent_ops; int i = 0; int retval = 0; #ifdef CONFIG_NET struct uevent_sock *ue_sk; #endif pr_debug("kobject: '%s' (%p): %s ", kobject_name(kobj), kobj, __func__); /* search the kset we belong to */ /*查找kobj所属的kset,看前面kset->kobj.kset = NULL,kset->kobj->parent = NULL*/ top_kobj = kobj; while (!top_kobj->kset && top_kobj->parent) top_kobj = top_kobj->parent; if (!top_kobj->kset) { pr_debug("kobject: '%s' (%p): %s: attempted to send uevent " "without kset! ", kobject_name(kobj), kobj, __func__); return -EINVAL; } /*kset = NULL*/ kset = top_kobj->kset; uevent_ops = kset->uevent_ops; /* skip the event, if uevent_suppress is set*/ /*如果被置1,不报uevent,看前面的代码,此位并没有被置位*/ if (kobj->uevent_suppress) { pr_debug("kobject: '%s' (%p): %s: uevent_suppress " "caused the event to drop! ", kobject_name(kobj), kobj, __func__); return 0; } /* skip the event, if the filter returns zero. */ /*kset->uevent_ops在此有用了,但kset->kobj.kset = NULL ,函数在此返回*/ if (uevent_ops && uevent_ops->filter) if (!uevent_ops->filter(kset, kobj)) { pr_debug("kobject: '%s' (%p): %s: filter function " "caused the event to drop! ", kobject_name(kobj), kobj, __func__); return 0; } /*下面的代码将在以后能执行至此的实例中分析*/ /* originating subsystem */ ............ } return 0; } if (error) { kfree(kset); return NULL; } return kset; }   对于kobject,以firmware为例   firmware_kobj = kobject_create_and_add("firmware", NULL); { struct kobject *kobj; int retval; /*创建kobj*/ kobj = kobject_create(); { struct kobject *kobj; /*为kobj申请内存*/ kobj = kzalloc(sizeof(*kobj), GFP_KERNEL); if (!kobj) return NULL; /*初始化kobj*/ kobject_init(kobj, &dynamic_kobj_ktype); { char *err_str; if (!kobj) { err_str = "invalid kobject pointer!"; goto error; } /*kobj 必须有ktype,此例为dynamic_kobj_ktype*/ 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); { if (!kobj) return; /*引用计数初始化为1*/ kref_init(&kobj->kref); /*list初始化*/ INIT_LIST_HEAD(&kobj->entry); /*还未在sysfs中创建目录*/ kobj->state_in_sysfs = 0; kobj->state_add_uevent_sent = 0; kobj->state_remove_uevent_sent = 0; /*初始化标志置1*/ kobj->state_initialized = 1; } /*kobj->ktype = dynamic_kobj_ktype*/ kobj->ktype = ktype; return; error: printk(KERN_ERR "kobject (%p): %s ", kobj, err_str); dump_stack(); } return kobj; } if (!kobj) return NULL; retval = kobject_add(kobj, parent, "%s", name); { 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); { int retval; /*设置kobj->name = “firmware”*/ retval = kobject_set_name_vargs(kobj, fmt, vargs); if (retval) { printk(KERN_ERR "kobject: can not set name properly! "); return retval; } /*设置kobj->parent = NULL*/ kobj->parent = parent; /*又是kobject_add_internal,是不是很熟悉,创建kset也走这个函数*/ return kobject_add_internal(kobj); { int error = 0; struct kobject *parent; if (!kobj) return -ENOENT; /* kobj->name = “firmware”*/ if (!kobj->name || !kobj->name[0]) { WARN(1, "kobject: (%p): attempted to be registered with empty " "name! ", kobj); return -EINVAL; } /*获取kobj的patent,前面初始化时设置为kobj.parent = NULL*/ parent = kobject_get(kobj->parent); /* join kset if set, use it as parent if we do not already have one */ /* 前面未初始kobj.kset则为NULL */ if (kobj->kset) { if (!parent) /*如果kobj有kset但没有parent,则将kset所谓parent*/ parent = kobject_get(&kobj->kset->kobj); /*将kobj键入kset->list中*/ kobj_kset_join(kobj); { if (!kobj->kset) return; kset_get(kobj->kset); spin_lock(&kobj->kset->list_lock); list_add_tail(&kobj->entry, &kobj->kset->list); spin_unlock(&kobj->kset->list_lock); } kobj->parent = parent; } pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s' ", kobject_name(kobj), kobj, __func__, parent ? kobject_name(parent) : "", kobj->kset ? kobject_name(&kobj->kset->kobj) : ""); /*在sys下创建firmware目录*/ error = create_dir(kobj); if (error) { kobj_kset_leave(kobj); kobject_put(parent); kobj->parent = NULL; /* be noisy on error issues */ if (error == -EEXIST) printk(KERN_ERR "%s failed for %s with " "-EEXIST, don't try to register things with " "the same name in the same directory. ", __func__, kobject_name(kobj)); else printk(KERN_ERR "%s failed for %s (%d) ", __func__, kobject_name(kobj), error); dump_stack(); } else /*已在sys创建firmware目录,将标记置1*/ kobj->state_in_sysfs = 1; return error; } } va_end(args); return retval; } if (retval) { printk(KERN_WARNING "%s: kobject_add error: %d ", __func__, retval); kobject_put(kobj); kobj = NULL; } return kobj; } /*创建kobj*/ kobj = kobject_create(); { struct kobject *kobj; /*为kobj申请内存*/ kobj = kzalloc(sizeof(*kobj), GFP_KERNEL); if (!kobj) return NULL; /*初始化kobj*/ kobject_init(kobj, &dynamic_kobj_ktype); { char *err_str; if (!kobj) { err_str = "invalid kobject pointer!"; goto error; } /*kobj 必须有ktype,此例为dynamic_kobj_ktype*/ 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); { if (!kobj) return; /*引用计数初始化为1*/ kref_init(&kobj->kref); /*list初始化*/ INIT_LIST_HEAD(&kobj->entry); /*还未在sysfs中创建目录*/ kobj->state_in_sysfs = 0; kobj->state_add_uevent_sent = 0; kobj->state_remove_uevent_sent = 0; /*初始化标志置1*/ kobj->state_initialized = 1; } /*kobj->ktype = dynamic_kobj_ktype*/ kobj->ktype = ktype; return; error: printk(KERN_ERR "kobject (%p): %s ", kobj, err_str); dump_stack(); } return kobj; } if (!kobj) return NULL; retval = kobject_add(kobj, parent, "%s", name); { 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); { int retval; /*设置kobj->name = “firmware”*/ retval = kobject_set_name_vargs(kobj, fmt, vargs); if (retval) { printk(KERN_ERR "kobject: can not set name properly! "); return retval; } /*设置kobj->parent = NULL*/ kobj->parent = parent; /*又是kobject_add_internal,是不是很熟悉,创建kset也走这个函数*/ return kobject_add_internal(kobj); { int error = 0; struct kobject *parent; if (!kobj) return -ENOENT; /* kobj->name = “firmware”*/ if (!kobj->name || !kobj->name[0]) { WARN(1, "kobject: (%p): attempted to be registered with empty " "name! ", kobj); return -EINVAL; } /*获取kobj的patent,前面初始化时设置为kobj.parent = NULL*/ parent = kobject_get(kobj->parent); /* join kset if set, use it as parent if we do not already have one */ /* 前面未初始kobj.kset则为NULL */ if (kobj->kset) { if (!parent) /*如果kobj有kset但没有parent,则将kset所谓parent*/ parent = kobject_get(&kobj->kset->kobj); /*将kobj键入kset->list中*/ kobj_kset_join(kobj); { if (!kobj->kset) return; kset_get(kobj->kset); spin_lock(&kobj->kset->list_lock); list_add_tail(&kobj->entry, &kobj->kset->list); spin_unlock(&kobj->kset->list_lock); } kobj->parent = parent; } pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s' ", kobject_name(kobj), kobj, __func__, parent ? kobject_name(parent) : "", kobj->kset ? kobject_name(&kobj->kset->kobj) : ""); /*在sys下创建firmware目录*/ error = create_dir(kobj); if (error) { kobj_kset_leave(kobj); kobject_put(parent); kobj->parent = NULL; /* be noisy on error issues */ if (error == -EEXIST) printk(KERN_ERR "%s failed for %s with " "-EEXIST, don't try to register things with " "the same name in the same directory. ", __func__, kobject_name(kobj)); else printk(KERN_ERR "%s failed for %s (%d) ", __func__, kobject_name(kobj), error); dump_stack(); } else /*已在sys创建firmware目录,将标记置1*/ kobj->state_in_sysfs = 1; return error; } } va_end(args); return retval; } if (retval) { printk(KERN_WARNING "%s: kobject_add error: %d ", __func__, retval); kobject_put(kobj); kobj = NULL; } return kobj; } 所以,从上面 看出无论kset还是kobject,最终都是根据kobject在sys下面创建目录的,其它几个的目录创建过程类似。