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

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创建一个符号链接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值