第一:sysfs设备驱动管理简介
sysfs是非持久性虚拟文件系统,它提供系统的全局视图,并通过它们的kobiect显示内核对象的层次结构(拓扑)。每个kobiect显示为录和目录中的文件,目录代表相关kobject导出的内核变量。这些文件称为属性,可以读取或写入。如果任何已注册的kobiect在sysfs中创建目录,则目录的创建位置取决于kobiec的父项(它也是kobiect)。这些目录自然创建为kobject父项的子目录。这向用户空间出显示了内部对象的层次结构。sysfs 中的顶级目录表示对象层次结构的共同祖先,即对象所属的子系统。
对系统上的每个块设备,block 都包含一个录,目录下包含设备上分区的子目录。bus 包含系统上注册的总线。dev 以原始方式(无层次结构)包含已注册的设备节点,每个节点都是/sys/devices目录中慎实设备的符号链接。devices 给出系统内设备的拓扑结构视图。firmware 显示系统相关的低层子系统树,如ACPI、EFI、 0F (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录下。它们直接有什么区别呢?
![](/qrcode.jpg)
-
●/dev录:该目录下面的文件是真实的设备文件,是应用层通过mknod创建的文件,通常系统中是由udev在运行时创建的。我们通常使用open、write、 ioctl 等函数操作设备,通常就是操作/dev目录下面的文件,它会间接调用到底层的驱动函数。
-
●/sys目录:这是由内核在运行时导出的,目的就是通过文件系统展示出设备、 驱动和总线等层次关系。这也是这章节的重点。那么先通过下图看一下 sysfs文件系统是如何搭建起来的,图中左边是初始化流程,右边是对应sysfs文件系统的目录结构。
可以看到sysfs并不单纯是设备驱动相关的,还包括了内核模块,内核参数以及电源等诸多管理,当然这些在某个角度上也可以视为设备或者驱动模块。不过它们不是我们分析的重点,我们着重需要分析的主要是设备驱动相关的,这图只是给了我们心中一个谱,知道它都有些什么,在哪里初始化的。
这里不准备直接通过sysfs文件目录层次结构进行分析sysfs对设备驱动的管理。我们从设备、驱动和总线等的注册添加和流程进行分析sysfs文件目录层次构造的。它们主要的注册函数分别为device_register、driver_register、bus_register,还有免不了的class_register。
第三:device_register主要功能
通过上图的device_register调用栈,可以看到设备主要的初始化都是在/sys/devices/***/下面创建一个自己名字的目录(例如xxx-device),然后在里面创建自己的属性文件接口。同时它会创建一个subsystem的链接,指向bus或者class,表示它归属的类型,挂在bus下面意味着它是由某个bus管控着,如果挂在class下面,这只是一个视角问题,其实质也是表示它具备某些共同属性,乃至管理操作属性上的一致。然后在/sys/bus或者/sys/class下面就没有必要创建重复的东西了,直接创建一个链接指向device,意味着从它们的目录去看,可以看到bus或者class都管着哪些设备。经过device_register后,创建的目录和链接关系如下:
这里的文件及目录的管理方式起本质是数据结构的管理思想,目录可以视为结构体,文件是数据结构成员,而链接文件是数据指针。上图实际上就是这几个数据结构除了自身的初始化外,然后就是建立结构之间的关联关系。
第四:driver_register都做了些什么?
那么通过接着看一下driver_register都做了些什么?
driver_register如上图调用关系,可以看到它比device的注册做的事情少多了。它主要是在/sys/bus/xxx-bus/drivers目录下创建自己名字的目录,然后在里面初始化驱动属性文件。同时创建链接指向module,表示该驱动是由哪个内核模块提供功能,同样module也反向指向驱动,表示它提供的是什么样的驱动能力,当然只有驱动模块才会有指向驱动的链接。经过driver_register后,其构成的目录和链接关系如下:
第五: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等设备的文件夹层层叠叠,这就涉及到了它们具体内部的一个管理关系了,这里不再叙述。
转载地址:https://www.elecfans.com/emb/202210141905091.html