最近在看linux设备驱动,下面将kobject内核对象和sysfs文件系统做一个简单小结,方便以后查阅。
1. kobject 是linux2.6内核引入的设备管理机制,在内核中由kobject结构体表示,这个结构体使所有设备在底层都有了统一的接口,kobject提供了基本的对象管理功能,是构成linux2.6设备模型的核心内容,每个内核在注册的kobject对象都对应于sysfs的一个目录,下面是kobject的定义(位于linux/kobject.h中),kobject类似于java这种面向对象语言中的object对象类, 提供了诸如引用计数、名称和父指针等字段,可以创建对象的层次结构。
struct kobject {
char * k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
struct kobject * parent;
struct kset * kset;
struct kobj_type * ktype;
struct dentry * dentry;
};
k_name指针指向kobject名称的起始位置,如果名称长度小于KOBJ_NAME_LEN——当前为20个字节,那么该kobject的名称便存 放到name数组中,k_name指向数组头;如果名称大于20,则动态分配以讹足够大的缓冲区来存放kobject的名称,这时k_name指向缓冲 区。
parent指针指向kobject的父对象。因此,kobject就会在内核中构造一个对象层次结构,并且可以将对各对象间的关系表现出来,就如你看到 的,这便是sysfs的真正面目:一个用户空间的文件系统,用来表示内核中kobject对象的层次结构。
dentry指针指向dentry结构体,在sysfs中该结构体就表示这个kobject,当然假设该kobject已反映在sysfs中。
kobject通常是嵌入到其他结构中的,其单独意义其实并不大。相反,那些更为重要的结构体才真正需要用到kobject结构。比如struct cdev。
struct cdev {
struct kobject kobj;
struct module *owner;
struct file_operations *ops;
struct list_head list;
dev_t dev
unsigned int count;
};
当kobject被嵌入到其他结构体中时,该结构体便拥有了kobject提供的标准功能。更重要的一点是,嵌入kobject接结构体可以成为对象层次 架构中的一部分。比如cdev结构体就可以通过其父进程指针cdev->kobj->parent和链表 cdev->kobj->entry来插入到对象层次结构中。
1.1 kobject的ktype成员是一个指向kobj_type结构的指针,是该对象的类型.定义于中:
struct kobj_type {
void (*release)(struct kobject *);
struct sysfs_ops * sysfs_ops;
struct attribute ** default_attrs;
};
ktype是为了描述一族kobject所具有的普遍特性。因此,不再需要每个kobject都分别定义自己的特性,而是将这些普遍的特性在ktype结 构体中一次定义,然后所有“同类”的kobject都能共享一样的特性。release指针指向在kobject引用计数减至0时要被调用的析构函数。该函数负责释放所有kobject使用的内存和其它相关清理工作。
1.1.1 sysfs_ops变量指向sysfs_ops结构体。该结构体描述了sysfs文件读写时的特性。其代码如下所示:
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *);
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
};
当从用户空间读取属性时,show()函数将被调用,该函数将指定属性值存入buffer中,返回给用户。而store()函数将用于存储用户通过buffer传入的属性值.和kobject不同的是,属性在sysfs中呈现为一个文件,而kobject则在sysfs中呈现为目录.
1.1.2默认属性
默认的文件集合是通过kobject和kset中的ktype字段提供的。因此所有具有相同类型的kobject在它们对应的sysfs目录下都拥有相同 的默认文件集合。kobj_type字段含有一个字段——default_attrs,它是看一个attribute结构体数组。这些属性负责将内核数据 映射成sysfs中的文件。
struct attribute {
char * name;
struct module * owner;
mode_t mode;
};
其中name字段提供了该属性的名称,最终出现在sysfs中的文件名就是它。owner字段在存在所属模块的情况下指向其所属的module结构体。如果一个模块没有该属性,那么该字段为NULL。mode字段类型为mode_t,他表示sysfs中该文件的权限。
default_attrs指向一个attribute结构体数组。这些结构体定义了该kobject相关的默认属性。属性给定了对象的特征, 如果该kobject被导出到sysfs中,那么这些属性都将相应的作为文件而导出。
2. kset
kset是kobject对象的集合体。把它看成一个容器,可将所有相关的kobject对象,比如“全部的块设备”置于同一位置。kset可把 kobject集中到一个集合中,而ktype描述相关类型kobject所共有的特性,它们之间的重要区别在于:具有相同ktype的kobject可 以分到不同的kset中。kobject的kset指针指向相应的kset集合。kobject经常通过kset组织成层次化结构。
kset结构体定义如下。位于内核代码linux/kobject.h中
struct kset {
struct subsystem * subsys;//所有在subsysterm中的指针
struct kobj_type * ktype;//指向该kset对象类型描述符的指针
struct list_head list;//用于连接所有kobject的链表头
struct kobject kobj;//嵌入的kobject
struct kset_hotplug_ops * hotplug_ops;//事件操作集
};
其中ktype指针指向集合(kset)中的kobject对象的类型(ktype),list连接该集合(kset)中所有的kobject对象。 kobj指向的kobject对象代表了该集合的基类。hotplug_ops指向一个用于处理集合中kobject对象的热拔插操作的结构体。 subsys指针指向该结构体相关的struct subsystem结构体。
4. subsystem
subsystem在内核中代表高层概念,它是一个或多个kset的大集合。
struct subsystem {
struct kset kset;//内嵌kset对象
struct rw_semaphore rwsem;//互斥访问信号量
};
虽然subsystem结构体只指向一个kset,但是多个kset可以通过其subsys指针指向一个subsystem这种单向关系意味着不可能仅仅 通过一个subsystem结构体就找到所有的ksets。subsystem中的kset字段指向的是subsystem中的默认kset,它在对象层 次结构中起到了粘合剂的作用。rwsem是一个读写信号量,它用来对subsystem和它的所有kset进行并发访问保护。
注意:每个kset必须属于一个subsystem
5 管理和操作kobject
5.1 Linux内核中提供了一系列操作kobject的函数, kobject的主要功能之一就是为我们提供了一个统一的引用计数系统。
void kobject_init(struct kobject *kobj);
该函数初始化后kobject,将引用计数设置为1。entry域指向自身,其所属kset引用指加1
Int kobject_set_name(struct kobject *kobj,const char *format,...);
该函数用于指定kobject的名称
struct kobject * kobject_get(struct kobject *kobj);
该函数增加一个引用计数,正常情况下返回一个指向kobject的指针,如果失败,则返回NULL指针。
void kobject_put(struct kobject *kobj);
该函数用于减少引用计数通过kobject_put()完成:
等等函数……
6. sysfs
sysfs文件系统是一个处于内存中的虚拟文件系统,它为我们提供了kobject对象层次结构的视图。帮助用户可以一个简单文件系统的方式来观察系统中 各种设备的拓扑结构。借助属性对象,kobject可用导出文件的方式,将内核变量提供给用户读取或写入。
sysfs的诀窍是把kobject对象与目录项紧密联系起来,这点是通过kobject中的dentry(directory entry)字段实现的。回忆一下12章,dentry结构体表示目录项,通过连接kobject到指定的目录项上,无疑方便的将kobject映射到该 目录上。好了,kobject其实已经形成了一棵树了——就是我们心爱的对象模型体系。
sysfs的根目录下包含了七个子目录:block、bus、class、devices、firmware、module和power。block目录 下的每个子目录都对应着系统中的一个块设备。反过来,每个目录下又都包含了该块设备的所有分区。bus目录提供了一个系统总线视图。class目录包含了 以高层功能逻辑组织起来的系统设备视图。devices目录是系统中设备拓扑结构视图,它直接映射出了内核中设备结构体的组织层次。firmware目录 包含一些诸如ACPI、EDD、EFI等低层子系统的特殊树。power目录包含了系统范围的电源管理数据。
阅读(464) | 评论(0) | 转发(0) |