2.2 kset内核对象集合
Kobject通常通过kset组织成层次化的结构,kset是具有相同类型的kobject的集合,在内核中用kset数据结构表示,定义为:
struct kset {
struct subsystem * subsys; 所在的subsystem的指针
struct kobj_type * ktype; 指向该kset对象类型描述符的指针
struct list_head list; 用于连接该kset中所有kobject的链表头
struct kobject kobj; 嵌入的kobject
struct kset_hotplug_ops * hotplug_ops; 指向热插拔操作表的指针
};
包 含在kset中的所有kobject被组织成一个双向循环链表,list域正是该链表的头。Ktype域指向一个kobj_type结构,被该 kset中的所有kobject共享,表示这些对象的类型。Kset数据结构还内嵌了一个kobject对象(由kobj域表示),所有属于这个kset 的kobject对象的parent域均指向这个内嵌的对象。此外,kset还依赖于kobj维护引用计数:kset的引用计数实际上就是内嵌的 kobject对象的引用计数。
2.3 subsystem内核对象子系统
Subsystem是一系列kset的集合,描述系统中某一 类设备子系统,如block_subsys表示所有的块设备,对应于sysfs文件系统中的block目录。类似的,devices_subsys对应于 sysfs中的devices目录,描述系统中所有的设备。Subsystem由struct subsystem数据结构描述,定义为:
struct subsystem {
struct kset kset; 内嵌的kset对象
struct rw_semaphore rwsem; 互斥访问信号量
};
每 个kset必须属于某个subsystem,通过设置kset结构中的subsys域指向指定的subsystem可以将一个kset加入到该 subsystem。所有挂接到同一subsystem的kset共享同一个rwsem信号量,用于同步访问kset中的链表。
3. 内核对象机制主要相关函数
针对内核对象不同层次的数据结构,linux 2.6内核定义了一系列操作函数,定义于lib/kobject.c文件中。
3.1 kobject相关函数
void kobject_init(struct kobject * kobj);
kobject初始化函数。设置kobject引用计数为1,entry域指向自身,其所属kset引用计数加1。
int kobject_set_name(struct kobject *kobj, const char *format, ...);
设置指定kobject的名称。
void kobject_cleanup(struct kobject * kobj)和void kobject_release(struct kref *kref);
kobject清除函数。当其引用计数为0时,释放对象占用的资源。
struct kobject *kobject_get(struct kobject *kobj);
将kobj 对象的引用计数加1,同时返回该对象的指针。
void kobject_put(struct kobject * kobj);
将kobj对象的引用计数减1,如果引用计数降为0,则调用kobject_release()释放该kobject对象。
int kobject_add(struct kobject * kobj);
将kobj对象加入Linux设备层次。挂接该kobject对象到kset的list链中,增加父目录各级kobject的引用计数,在其parent指向的目录下创建文件节点,并启动该类型内核对象的hotplug函数。
int kobject_register(struct kobject * kobj);
kobject注册函数。通过调用kobject_init()初始化kobj,再调用kobject_add()完成该内核对象的注册。
void kobject_del(struct kobject * kobj);
从Linux设备层次(hierarchy)中删除kobj对象。
void kobject_unregister(struct kobject * kobj);
kobject注销函数。与kobject_register()相反,它首先调用kobject_del从设备层次中删除该对象,再调用kobject_put()减少该对象的引用计数,如果引用计数降为0,则释放该kobject对象。
3.2 kset相关函数
与kobject 相似,kset_init()完成指定kset的初始化,kset_get()和kset_put()分别增加和减少kset对象的引用计数。 Kset_add()和kset_del()函数分别实现将指定keset对象加入设备层次和从其中删除;kset_register()函数完成 kset的注册而kset_unregister()函数则完成kset的注销。
3.3 subsystem相关函数
subsystem有一组完成类似的函数,分别是:
void subsystem_init(struct subsystem *subsys);
int subsystem_register(struct subsystem *subsys);
void subsystem_unregister(struct subsystem *subsys);
struct subsystem *subsys_get(struct subsystem *subsys)
void subsys_put(struct subsystem *subsys);
