上一篇文章简要介绍了sysfs文件系统的注册以及挂载流程,本小节主要介绍sysfs相关的结构体,以便我们可以更深入的理解sysfs。
- 相关结构体说明
我们介绍sysfs相关的结构体,主要是想从结构体之间的联系,建立对sysfs文件系统实现框架的感性认识,以便我们更好的理解sysfs文件系统。
在我们对单个结构体进行分析之前,我们先来看下这些结构体的关系,如下所示主要包
括kset、kobject、kref、sysf_dirent、kobj_type、sys_ops、sysfs_elem_dir
、sysfs_elem_symlinks、sysfs_elem_attr、sysfs_elem_bin_attr结构体。主要包括sysfs与设备模型关联的结构体、sysfs文件系统目录及文件建立相关、sysfs文件操作相关的结构体等几大部分。
如上图所示,一个kset结构体变量包括一类kobject的集合,而针对一个kset而言,且也是一个目录,因此其也有相应的kobject,而关于kset的引用计数,直接使用kobject->kref实现引用计数的功能。而针对一个kobject而言,其也有相应的方法,即kobj_type,该方法中包括kobject的释放以及show/store接口,还包括默认的属性参数等
下面我们按上面的分类分别介绍这几类结构体的定义与关联。
sysfs与设备模型关联的结构体
与设备模型相关的结构体主要为kset、kobject、kref、sysfs_dirent等,其中kobject表示内核对象,定义了内核对象后,则针对每一个设备类型、驱动类型、总线类型等,均可用一个内核对象表示,在sysfs中一个kobject即代表一个目录,针对sysfs的文件,是没有对应的kobject,kobject仅表示目录。而在设备模型中,针对设备、驱动以及总线而言,均会有对应的内核对象,而针对总线而言,其还会包含kset变量,并通过该kset变量的list成员变量,链接bus下所有具体已注册总线的内核对象(kobject)。通过这几个变量,就实现了与设备驱动模型的关联。
这些结构体的关联如下:
struct kobject定义说明
下面我们看下kobject的定义,主要包括对象命令、引用计数、对应的sysfs_dirent指针、该kobject所属的kset等。
struct kobject {
const char *name;//本kobject的名称
struct list_head entry;//同属于一个kset的kobject子项的链表
struct kobject *parent;//该kobject对应的父对象
struct kset *kset;//该kobject所属的kset
struct kobj_type *ktype;//包括该对象的释放接口、属性操作接口、默认属性等
struct sysfs_dirent *sd;//该kobject对应的sysfs_dirent指针
struct kref kref;//该kobject的引用计数
unsigned int state_initialized:1;
unsigned int state_in_sysfs:1;
unsigned int state_add_uevent_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int uevent_suppress:1;
};
struct kset定义说明
主要包括属于该kset的kobject的链表头、该kset对应的内核对象、kset对应的事件处理接口等
struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops;
};
struct kref定义
该结构体就是一个原子变量,用于kobject的引用计数。
struct kref {
atomic_t refcount;
};
struct kobj_type定义
该结构体主要是kobject对应的释放接口以及属性操作接口(属性操作接口,主要用于该对象下文件的读写操作)
struct kobj_type{
void (*release)//kobj的释放接口
struct sysfs_ops *sysfs_ops
attribute **default_attrs
...
};
struct sysfs_ops定义
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *);
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
const void *(*namespace)(struct kobject *, const struct attribute *);
};
该结构体主要包括show、store、namespace三个接口指针,其中show、store主要用于属性对应文件的读与写接口,这两个接口需要输入的参数包括kobject、attribute结构体对应的变量。
struct attribute结构体说明
针对上述的结构体变量attribute,系统中各子模块可通过创建包含该结构体变量attribute的私有变量,从而实现针对具体属性的show/store接口的调用。
我们以struct bus_attribute 结构体变量为例进行简要说明。针对bus目录而言,在进行总线的注
册时,其kobject对象的struct kobj_type变量定义为bus_ktype,其中定义了bus目录对应的show/store接口为bus_attr_show/bus_attr_store,而bus对应的属性结构体为bus_attribute,包含了struct attribute成员变量、show/store接口指针(这个show/store接口即为具体文件的处理接口),当在bus目录下创建文件时,则会创建bus_attribute结构体的变量,而在bus_attr_show/bus_attr_store接口中会根据传入的attribute结构体变量,从而获取bus_attribute结构体类型的变量,然后就调用bus_attribute结构体类型变量的show/store接口,从而实现对具体文件的show/store操作。
struct bus_attribute {
struct attribute attr;
ssize_t (*show)(struct bus_type *bus, char *buf);
ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
};
static const struct sysfs_ops bus_sysfs_ops = {
.show = bus_attr_show,
.store = bus_attr_store,
};
static struct kobj_type bus_ktype = {
.sysfs_ops = &bus_sysfs_ops,
};
sysfs文件系统目录及文件建立相关
sysfs也是内存文件系统,而且sysfs文件系统不允许通过应用层创建文件及目录,而且sysfs文件系统也不再以inode、dentry接口来创建文件及目录,其通过结构体sysfs_dirent进行文件及目录的创建以及关联(该结构体通过红黑色进行关联)。
该结构体的定义如下,主要包括文件或目录的类型(目录、链接、属性文件、bin文件)、红黑树节点、所属的父目录等。
struct sysfs_dirent {
atomic_t s_count;//引用计数
atomic_t s_active;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
struct sysfs_dirent *s_parent;//该文件或者目录的父目录
const char *s_name;//名称
struct rb_node s_rb;//对应的红黑树节点
union {
struct completion *completion;
struct sysfs_dirent *removed_list;
} u;
const void *s_ns; /* namespace tag */
unsigned int s_hash; /* ns + name hash */
/*标识该目录或文件的类型,目录、链接、属性文件、bin文件等*/
union {
struct sysfs_elem_dir s_dir;
struct sysfs_elem_symlink s_symlink;
struct sysfs_elem_attr s_attr;
struct sysfs_elem_bin_attr s_bin_attr;
};
unsigned short s_flags;
umode_t s_mode;//该目录或文件的权限
unsigned int s_ino;
struct sysfs_inode_attrs *s_iattr;
};
struct sysfs_elem_dir
该结构体表示目录,主要包括内核对象、子目录属性、该目录的红黑树子节点灯
struct sysfs_elem_dir {
struct kobject *kobj;
unsigned long subdirs;
/* children rbtree starts here and goes through sd->s_rb */
struct rb_root children;
};
struct sysfs_elem_symlink
该结构体表示一个链接,针对链接目录或文件,则主要是该链接对应的目标sysfs_dirent变量
struct sysfs_elem_symlink {
struct sysfs_dirent *target_sd;
};
struct sysfs_elem_attr
该结构体表示一个属性文件,其中包括attribute结构体变量(该结构体主要用于获取该属性文件对应的操作接口,在上面的“struct attribute结构体说明”中已经分析过),而结构体变量sysfs_open_dirent主要是建立属性文件和打开该文件的所有文件描述符的关联。
struct sysfs_elem_attr {
struct attribute *attr;
struct sysfs_open_dirent *open;
};
sysfs文件操作相关的结构体
在上面介绍struct sysfs_elem_attr时,已经提到了sysfs_open_dirent结构体,下面我们详细说明属性文件相关的结构体,主要包括sysfs_elem_attr、sysfs_open_dirent、sysfs_buffer等,这些结构体之间的关联如下所示,其中sysfs_open_dirent主要是建立属性文件和打开该文件的所有文件描述符的关联,如下所示sysfs_open_dirent中的链表成员buffers链接了所有已打开该文件的sysfs_buffer变量(该变量中包括了文件读写的偏移量、读取时是否需要重新刷新变量值、发生事件计数等信息),而每一个sysfs_buffer结构体变量作为文件描述符的私有指针成员变量,完成与文件描述符的关联。
struct sysfs_open_dirent {
atomic_t refcnt;//引用计数
atomic_t event;//事件计数
wait_queue_head_t poll;//poll机制对应的等待队列头,用于实现属性文件的poll机制,以便进行属性文件相关的事件触发。
struct list_head buffers; /*链接所有的 sysfs_buffer变量*/
};
struct sysfs_buffer {
size_t count;//数据内容长度
loff_t pos;//当前的偏移量
char * page;//存放读写相关的内容
const struct sysfs_ops * ops;//show/store接口,在属性文件的open接口sysfs_open_file中会对该变量进行赋值
struct mutex mutex;
int needs_read_fill;//指示是否需要更新该buff中page中的内容
int event;//已发生的事件计数
struct list_head list;
};
以上主要介绍了kset、kobject、kref、sysfs_dirent、sysfs_buffer、sysfs_elem_attr、sysfs_ops、attribute等变量,包含了与设备模型、文件描述符、sysfs文件及目录的创建及访问等内容。下一篇文件介绍sysfs相关的目录与文件创建流程。