沉淀、分享、成长,让自己和他人都能有所收获!?
?Linux
系统中一切皆文件。
一、什么是Sysfs设备驱动管理
sysfs
是非持久性虚拟文件系统,它提供系统的全局视图,并通过它们的kobiect
显示内核对象的层次结构(拓扑)。每个kobiect
显示为目录和目录中的文件,目录代表相关kobject
导出的内核变量。这些文件称为属性,可以读取或写入。如果任何已注册的kobiect
在sysfs
中创建目录,则目录的创建位置取决于kobiec
的父项(它也是kobiect
)。这些目录自然创建为kobject
父项的子目录。这向用户空间出显示了内部对象的层次结构。sysfs
中的顶级目录表示对象层次结构的共同祖先,即对象所属的子系统。
对系统上的每个块设备,block
都包含一个目录,目录下包含设备上分区的子目录。bus
包含系统上注册的总线。dev
以原始方式(无层次结构)包含已注册的设备节点,每个节点都是/sys/devices
目录中真实设备的符号链接。devices
给出系统内设备的拓扑结构视图。firmware
显示系统相关的低层子系统树,如ACPI
、EFI
、OF
(DT
)。fs
列出系统上实际使用的文件系统。kernel
保存内核配置选项和状态信息。module是加载的模块列表。
kernel_kobj
:对应于/sys/kernel
。power_kobj
:对应于/sys/power
。firmware_kobj
:对应于/sys/firmware
,导出在drivers/baselirmware.c
源文件中。hvpervisor_kobj
:对应于/sys/hypervisor
,导出在drivers/base hypervisor.c
中。fs_kobj
:对应于/sys/fs,导出在fs/namespace.c文件中。
然而,class/
、dev/
、devices/
是在启动期间由内核源代码内drivers_base/core.c
中的devices_init
函数创建的,block/
在block/genhd.c
中创建,bus/
在drivers/base/bus.c
中被创建为kset.
kobject
目录被添加到sysfs
(使用kobject_add
)时,其添加位置取决于kobject
的父项。如果其父指针已设置,则它将被添加为父目录内的子目录。如果父指针为NULL
,则将其添加为kset->kobj内的子目录。如果其父和kset字段都未设置,它将映射到sysfs内的根目录(/sys)。
二、Sysfs设备驱动管理相关注册接口
Linux
系统中一切皆文件。
设备文件在哪里呢?它在/dev
目录下,也在/sys
目录下。它们直接有什么区别呢?
/dev
目录:该目录下面的文件是真实的设备文件,是应用层通过mknod
创建的文件,通常系统中是由udev
在运行时创建的。我们通常使用open
、write
、ioctl
等函数操作设备,通常就是操作/dev
目录下面的文件,它会间接调用到底层的驱动函数。/sys
目录:这是由内核在运行时导出的,目的就是通过文件系统展示出设备、驱动和总线等层次关系。这也是这章节的重点。
那么先通过下图看一下sysfs
文件系统是如何搭建起来的,图中左边是初始化流程,右边是对应sysfs文件系统的目录结构。
可以看到sysfs
并不单纯是设备驱动相关的,还包括了内核模块、内核参数以及电源等诸多管理,当然这些在某个角度上也可以视为设备或者驱动模块。不过它们不是我们分析的重点,我们着重需要分析的主要是设备驱动相关的,这图只是给了我们心中一个谱,知道它都有些什么,在哪里初始化的。
这里不准备直接通过sysfs
文件目录层次结构进行分析sysfs
对设备驱动的管理。我们从设备、驱动和总线等的注册添加流程进行分析sysfs
文件目录层次构造的。它们主要的注册函数分别为device_register
、driver_register
、bus_register
,还有免不了的class_register
。
2.1、device_register都做了些什么?
通过上图的device_register
调用栈,可以看到设备主要的初始化都是在/sys/devices/***/
下面创建一个自己名字的目录(例如xxx-device
),然后在里面创建自己的属性文件接口。同时它会创建一个subsystem
的链接,指向bus
或者class
,表示它归属的类型,挂在bus
下面意味着它是由某个bus
管控着,如果挂在class
下面,这只是一个视角问题,其实质也是表示它具备着某些共同属性,乃至管理操作属性上的一致。然后在/sys/bus
或者/sys/class
下面就没有必要创建重复的东西了,直接创建一个链接指向device
,意味着从它们的目录去看,可以看到bus
或者class
都管着哪些设备。经过device_register
后,创建的目录和链接关系如下:
这里的文件及目录的管理方式起本质是数据结构的管理思想,目录可以视为结构体,文件是数据结构成员,而链接文件是数据指针。上图实际上就是这几个数据结构除了自身的初始化外,然后就是建立结构之间的关联关系。
2.2、driver_register都做了些什么?
那么通过接着看一下driver_register
都做了些什么?
driver_register
如上图调用关系,可以看到它比device
的注册做的事情少多了。它主要是在/sys/bus/xxx-bus/drivers
目录下创建自己名字的目录,然后在里面初始化驱动属性文件。同时创建链接指向module
,表示该驱动是由哪个内核模块提供功能,同样module
也反向指向驱动,表示它提供的是什么样的驱动能力,当然只有驱动模块才会有指向驱动的链接。经过driver_register
后,其构建的目录和链接关系如下:
接着看一下bus_register
都做了什么?
2.2、bus_register都做了些什么?
通过上图可以看到,它主要是在/sys/bus
目录下面创建以自己名字命名的bus
目录(这里名字举例为xxx-bus
),然后会创建好devices
和drivers
给与它管理的设备和驱动进行注册,同时创建驱动的探测drivers_probe
和drivers_autoprobe
属性文件,以提供给用户触发去探测。当然还少不了uevent
事件文件的创建,最后还有一些bus自己特有的属性。注册完bus
后,将会生成目录结构如下:
最后看一下class_register
都做了些什么?
class_register
的行为比较简单,仅仅是在/sys/class
下面创建一个自己名字命名的目录,主要是提供给设备注册挂入链接。挂链接的动作在device_register
里面完成。
至此,我们就大概对sysfs
文件系统上的设备驱动注册和大概的关系逻辑了。如果通过tree
命令去查看/sys
肯定会发现/sys/devices
目录下面的PCI
、USB
等设备的文件夹层层叠叠,这就涉及到了它们具体内部的一个管理关系了,这里不进行展开叙述。



评论记录:
回复评论: