2.6内核增加了一个引人注目的新特性——统一设备模型(device model)。设备模型提供了一个独立的机制专门来表示设备,并描述其在系统中的拓扑结构;
Linux设备模型的核心是使用Bus、Class、Device、Driver四个核心数据结构,将大量的、不同功能的硬件设备(以及驱动该硬件设备的方法),以树状结构的形式,进行归纳、抽象,从而方便Kernel的统一管理;
而硬件设备的数量、种类是非常多的,这就决定了Kernel中将会有大量的有关设备模型的数据结构。这些数据结构一定有一些共同的功能,需要抽象出来统一实现,否则就会不可避免的产生冗余代码。这就是Kobject诞生的背景;
通过parent指针,可以将所有Kobject以层次结构的形式组合起来;
使用一个引用计数(reference count),来记录Kobject被引用的次数,并在引用次数变为0时把它释放(这是Kobject诞生时的唯一功能);
和sysfs虚拟文件系统配合,将每一个Kobject及其特性,以文件的形式,开放到用户空间(有关sysfs,会在其它文章中专门描述,本文不会涉及太多内容);
Kobject是Linux设备模型的基础;
回想文件系统中的核心对象“索引节点(indoe)”和目录项“dentry”:
inode—与文件系统中的一个文件相对应(而实际上,只有文件被访问时,才在内存创建索引节点);
dentry—每个路径中的一个分量,例如路径/bin/ls,其中/、bin和ls三个都是目录项,只是前两个是目录,而最后一个是普通文件;也就是说,目录项或者是一子目录,或者是一个文件;
既然,kobject要形成一颗树,那么其中的字段就要有parent,以表示树的层次关系;另外,kobject得有name字段,按说,目录或文件名并不会很长,但是,sysfs文件系统为了表示对象之间复杂的关系,需要通过软链接达到,而软链接常常有较长的名字,通过以上的分析,目前可以得知kobject对象包含的字段有:
struct kobject {
char *k_name; /*长名字*/
char name[kOBJ_NAME_LEN]; /* 短名字*/
struct kobject *parent; /* 表示对象的层次关系*/
struct dentry *dentry; /*表示sysfs中的一个目录项 */
};
查看kobject.h头文件,看到它还包含以下字段:
struct kobject {
struct kref kref;
struct list_head entry;
struct kset *kset;
struct kobj_type *ktype;
};
这四个字段,每一个都是结构体,其中structlist_head是内核中形成双向链表的基本结点结构;
增加一个引用计数可通过koject_get()函数完成:
struct kobject* kobject_get(struct kobject *kobj);
该函数正常情况下将返回一个指向kobject的指针,如果失败则返回NULL指针;
减少引用计数通过kobject_put()完成:
void kobject_put(struct kobject *kobj);
如果对应的kobject的引用计数减少到零,则与该kobject关联的ktype中的析构函数将被调用;
深入到引用计数系统的内部去看,会发现kobject的引用计数是通过kref结构体实现的,该结构体定义在头文件<linux/kref.h>中:
struct kref {atomic_t refcount;};
其中唯一的字段是用来存放引用计数的原子变量。那为什么采用结构体?这是为了便于进行类型检测;
上述的所有函数定义与声明分别在在文件lib/kref.c和文件<linux/kref.h>中。
共同特性的ktype
kobject是一个抽象而基本的对象。对于一族具有共同特性的kobject,就是用定义在头文件<linux/kobject.h>中的ktype来描述:
struct kobj_type {
void (*release)(structkobject *);
struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
};
release指针指向在kobject引用计数减至零时要被调用的析构函数,该函数负责释放所有kobject使用的内存和其它相关清理工作;
sysfs_ops变量指向sysfs_ops结构体,其中包含两个函数,也就是对属性进行操作的读写函数show()和store();
最后,default_attrs指向一个attribute结构体数组。这些结构体定义了kobject相关的默认属性;属性描述了给定对象的特征,其实,属性就是对应/sys树形结构中的叶子结点,也就是文件;