2.2、kobject、kset和subsystem
2.2.1、kobject
设备驱动程序模型的核心数据结构是kobject,每个kobject对应于sysfs文件系统中的一个目录。
kobject被嵌入到一个叫做”容器”的更大对象中,容器描述设备驱动程序模型中的组件,典型的容器例子有总线、设备及驱动程序的描述符。
<linux/kobject.h>
struct kobject { const char * k_name; /*指向含有容器名称的字符串*/ struct kref kref; /*容器的引用计数器*/ struct list_head entry; /*用于kobject所插入的链表的指针*/ struct kobject * parent; /*指向父kobject (如果存在)*/ struct kset * kset; /*指向包含的kset*/ struct kobj_type * ktype; /*指向kobject的类型描述符*/ struct sysfs_dirent * sd; /*指向与该kobject相对应的sysfs文件的sysfs_dirent数据结构*/ };
Ktype字段指向kobj_type对象,该对象描述了kobject的“类型”-------本质上,它描述的是包括kobject的容器的类型。
struct kobj_type { void (*release)(struct kobject *); /*当kobject被释放时执行*/ struct sysfs_ops * sysfs_ops; /*指向sysfs操作表的sysfs_ops指针*/ struct attribute ** default_attrs; /*sysfs文件系统的缺省属性链表*/ };
<linux/sysfs.h>
struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); };
<linux/sysfs.h>
/* FIXME * The *owner field is no longer used, but leave around * until the tree gets cleaned up fully. */ struct attribute { const char *name; struct module *owner; mode_t mode; };
字段kref字段是一个k_ref类型结构,该字段是kobject的引用计数器。但它也可以作为kobject容器的引用计数器。
<linux/kref.h>
struct kref { atomic_t refcount; };
2.2.2、kset
函数kobject_get()和kobject_put()分别用于增加和减少引用计数器的值,如果该计数器的值等于0,就会释放kobject使用的资源,并且执行kobject的类型描述符kobj_type对象的release方法。该方法用于释放容器本身,通常只有在动态分配kobject容器时才定义该方法。
通过kset可将kobjects组织成一棵层次树。kset是同类型kobject的一个集合体-------也就是说,相关的kobject包含在同类型的容器中。
<linux/kobject.h>
/** * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem. * * A kset defines a group of kobjects. They can be individually * different "types" but overall these kobjects all want to be grouped * together and operated on in the same manner. ksets are used to * define the attribute callbacks and other common events that happen to * a kobject. * * @ktype: the struct kobj_type for this specific kset * @list: the list of all kobjects for this kset * @list_lock: a lock for iterating over the kobjects * @kobj: the embedded kobject for this kset (recursion, isn't it fun...) * @uevent_ops: the set of uevent operations for this kset. These are * called whenever a kobject has something happen to it so that the kset * can add new environment variables, or filter out the uevents if so * desired. */ struct kset { /*指向kset的kobject类型描述符,该描述符被kset中所有kobject共享*/ struct kobj_type *ktype; x struct list_head list; /*包含在kset中的kobject双向循环链表的首部*/ spinlock_t list_lock; struct kobject kobj; /*嵌入的kobject结构*/ struct kset_uevent_ops *uevent_ops; };
字段kobj是嵌入在kset中的kobject,而位于kset中的kobject,其parent字段指向这个内嵌的kobject结构。一次,一个kset是kobject集合体,但是它依赖于层次树中用于引用计数和连接的更高层kobject。这种编码效率很高,灵活性很高。
分别用于增加和减少kset引用计数器值的kset_get()和kset_put(),只需简单的调用内嵌kobject结构的kobject_get()和kobject_put()即可,因为kset的引用计数器即是其内嵌kobject的引用计数器。而且有了内嵌的kobject结构,kset数据结构可以嵌入到”容器”对象中,非常类似嵌入的kobject数据结构。最后kset可以作为其他kset的一个成员:它足以将内嵌的kobject插入到更高层次的kset中。
<linux/kobject.h>
struct kset_uevent_ops { int (*filter)(struct kset *kset, struct kobject *kobj); const char *(*name)(struct kset *kset, struct kobject *kobj); int (*uevent)(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env); };
2.2.3、subsystem
现在已经没有该结构体定义。但subsystem是kset的集合,一个subsystem可以包含不同类型的kset.
2.2.4、注册kobject、kset和subsystem
一般来讲,如果想让kobject、kset或subsystem出现在sysfs子树中,就必须首先注册它们。与kobject对应的目录总是出现在其父kobject的目录中,例如,位于同一个kset中的kobject的目录就出现在kset本身的目录中(kobject->parent指向其所在kset的内嵌kobject)。因此sysfs子树的结构就描述了各种已注册kobject之间以及各种容器对象之间的层次关系。
通常,sysfs文件系统的上层目录肯定是已注册的subsystem。
常用的函数有:
l kobject_register(struct kobject * kobj)
用于初始化kobject,并将其相应的目录增加到sysfs文件系统中,在调用该函数之前,调用程序应先设置kobject中的kset字段,使它指向其父set(如果存在)。
l kobject_unregister(struct kobject * kobj)
将kobject目录从sysfs文件系统中移走
l kset_register(struct kset * k)
l kset_unregister(struct kset * k)
l subsystem_register
l subsystem_unregister()
int subsystem_register(struct kset *s) { return kset_register(s); } void subsystem_unregister(struct kset *s) { kset_unregister(s); }
许多kobject目录都包括称为attribute的普通文件。S
<sysfs/file.c>
/** * sysfs_create_file - create an attribute file for an object. * @kobj: object we're creating for. * @attr: attribute descriptor. */ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) 接收kobject的地址和属性描述符作为参数,并在合适目录中创建特殊文件。
Sysfs文件系统中所描述的对象间其他关系可用符号链接方式建立:sysfs_create_link()为目录中与其他kobject相关联的特定kobject创建一个符号链接。