您的位置:首页 > 其它

I/O体系结构和设备驱动程序(二)

2011-08-06 19:15 393 查看

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创建一个符号链接。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: