1.sysfs起源
linux设备驱动模型由大量的数据结构与算法组成,这里面关系很复杂,结构和结构之间一般使用指针连接。
构成树或网状结构。而描述这种结构的最好的方法是利用一种树形的一些文件系统。
linux设备驱动模型中的肯定是要挂载设备信息,驱动和总线信息的,所以这种文件系统肯定是要和其他类型的文件系统不一样,要有自己的特殊之处(ext2用于快速读写存储文件,ext3用于记录日志文件),正是因为有着不同之处,才被称为sysfs
2.sysfs
- sysfs只存在与内存中,内核需要的设备驱动模型的信息会从这个文件系统导入到用户内存中
- sysfs是一种树形关系的文件系统,每个目录下都可能有其他目录和一些属性文件
- 是内核对象(kobject),属性(kobj_type)以及他们的相互关系的一种表现机制
- sysfs提供了用户读取内核的数据,以及用户空间向内核写入数据的双向通道,以此设置驱动程序的属性和状态
3.内核中的结构和sysfs的对应关系
Linux内核中的结构 | sysfs中的结构 |
---|---|
kobject | 目录 |
kobj_type | 属性文件 |
对象之间的关系 | 符号链接 |
4.sys目录下
5.设备驱动模型中的核心数据结构
设备驱动模型是一个层次化的结构,在内核中就通过kobject,kset,subsystem这几个结构体描述。这种层次化的结构可以将驱动,设备,总线等联系起来。
5.1 kobject结构体
一般来说我们可以用这样的树形结构去表示设备驱动模型中dev-drv-bus的层次结构:
这个结构在sysfs文件系统中将会以这样形式存在:
这节的主角kobject与就与下面的目录一一对应,kobject里描述了目录的组织结构和名字
kobject结构体是组成驱动模型的基本结构
每一个在内核中注册的kobject对象都对应于sysfs文件系统中的一个目录
kobject的结构体如下:(include/linux/kobject.h)
64行 name存储kobject结构体名称,该名称对应着目录的名字
65行 list_head和第二节中cdev结构体里的是用一个结构体,用于连接下一个kobject结构
66行 parent变量用于连接其父目录所代表的kobject结构体
67行 kset用于组成层次化的结构,他是具有想同类型的kobject集合 后面会详细说
68行 kobj_type用于指向kobject的类型描述符,代表kobject属性,对应着sysfs中的一个属性文件
69行 sd对应sysfs的文件目录
70行 kref为kobject的引用计数
74行 state_initialized用位域表示该kobject是否被初始化过
75行 state_in_sysfs表示是否注册进sysfs文件系统
5.2 Kobject如何初始化
首先应使用memset函数将kobject置0
然后调用kobject_init()
:
源码如下(\linux-4.9.229\arch\powerpc\platforms\powernv\opal-dump.c)
首先是两个检查:
检查传入的kobj ktype指针是否指向空
再检查kobj是否被初始化
随后调用kobject_init_internal
最后使用传入的ktype初始化kobject的ktype
kobject_init_internal源码:(lib\kobject.c)
这个函数主要是对kobject进行初始化:
kref引用计数初始化
并且初始化kobj的entry指针,这里面其实就是初始化一个双向链表(数据结构知识)
并标记kobject还没有注册到sysfs文件系统
设置该结构体已经被初始化过了
kobject计数引用
对于kref值的引用计数控制
增加kref的计数使用kobject_get(内部调用kref_get)
减少kref的计数使用kobject_put(内部调用kref_put)
源码和英文注释如下:
可以在kref_put的参数列表里发现release函数
这是个回调函数,kobject引用计数为0的时候,需要释放kobject对象和其占用的资源,无法做一个单独的函数作为释放函数,因为每个设备所用资源都是不一样的,所以就需要驱动开发程序员去自己实现释放资源函数
这个释放函数会在资源引用数为0时被系统自动调用。
5.3 kobj_type
kobj_type对应sysfs文件系统里的属性文件,指代设备的一些属性
一开始kobj_type结构只是放在kobject结构中的成员
后来发现这个东西可以复用,因为同一类设备,会有相同的属性,创建每个kobject都要重复创建type实在太麻烦
所以就把它单独做了个结构体:(include/linux/kobject.h)
进行到此刻可以先纵观一下Kobject与kobj_type之间的关系:
kobject包含ktype指针,初始化时要将ktype指针指向初始化好的ktype结构体
kobject中的parent指针
ktype结构体里面三个重要的release, sysfs_ops , attribute结构体
release需要程序员自己实现的资源释放函数
sysfs_ops表示对属性操作的函数
attribute表示属相集合
一个kobject可以有多个ktype即一个目录下可以有多个属性文件