本系列前几篇文章链接如下:
《LINUX设备驱动模型分析之一 总体概念说明》
《LINUX设备驱动模型分析之二 总线(BUS)接口分析》
上一章我们分析了bus-driver-device模型中bus接口部分,本章我们将分析driver接口,在bus-driver-device模型中,driver接口是依附于bus上,而不像device有独立统一的kset,而driver接口是依附于具体类型的bus总线。针对bus-driver-device这三类模块之间的关联与区别,我们在总线接口分析时,已经分析过,此处不再赘述,仅引用
《LINUX设备驱动模型分析之一 总体概念说明》中的一张图,试图再次说明bus-driver-device之间的关联。
如下图所示,所有注册的设备均在sysfs的device(即通过devices_kset将所有device对应的kobject链接在一起),而具体bus_type->p->devices_kset->kobj则对该总线下所有注册的设备,创建链接目录,用以链接至devices_kset下汇聚的kobject。
针对driver接口,相对来说内容也不复杂,本章我们还是从数据接口、driver的注册以及注销接口进行分析驱动接口。
相关结构体分析
针对driver子模块而言,涉及的结构体主要包括device_driver、driver_private,其中device_driver用于抽象驱动类,而具体的驱动可理解为一个驱动对象,而driver_private则主要用于链接至sysfs、bus模块、device模块。下面我们介绍这两个结构体变量。
struct device_driver 结构体分析
该结构体包含的内容可梳理为如下几个部分:
- 性能管理部分,主要与性能管理模块管理(非本次分析内容,暂不展开,这块我还不熟);
- 该驱动相关的接口指针,包括probe、remove等,其中
- probe为该驱动的探测接口,实现对设备的探测操作(包括设备相关的寄存器初始化、中断初始化等);
- remove为该驱动的移除接口,当需要移除一个驱动模块时,则调用该接口实现移除接口
- shutdown、suspend、resume主要为电源管理相关的接口;
- of_device_id类型的变量主要为设备树所用,该结构体变量中会定义该驱动所支持的of device,用compatible值表示支持的of device的名称。
- 该驱动所包含的属性,通过attribute_group类型的变量传递该驱动所有的默认属性;
- 通过driver_private类型的变量,包含了该驱动与sysfs、device、bus之间关联的关联;
- 通过定义kobject类型的变量,为该变量在sysfs文件系统中创建了该驱动对应的命令;
- 通过klist_device,链接所有该驱动支持且绑定的设备;
- 通过knode_bus将该驱动链接至总线的驱动链表中;
- 通过module_kobject类型的变量,将该驱动与module模块关联(本次不对module模块关联);
- 通过bus_type类型的关联,说明本驱动所依附的总线。
struct driver_private结构体分析
该结构体变量主要是包含了与driver、device、bus、sysfs模块关联的结构体变量,其中
- 通过定义kobject类型的变量,为该变量在sysfs文件系统中创建了该驱动对应的命令;
- 通过klist_device,链接所有该驱动支持且绑定的设备;
- 通过knode_bus将该驱动链接至总线的驱动链表中;
- 通过module_kobject类型的变量,将该驱动与module模块关联(本次不对module模块关联);
以上便是driver模块相关的结构体变量,为了让我们更好的理解bus-driver-device,我们现将bus_type、device_driver、kobject、driver_private等结构体变量的关联关系画出来,以此说明driver模块在bus-driver-device中的位置,以及是如何与sysfs进行关联的。
如下图为 bus_type、device-driver、kobject相关结构体之间的关联,该图说明了
bus_type、device-driver、kobject之间的关联。我们分几个方面进行说明:
- 系统下所有已注册bus_type类型的关联(这些已在上一篇文章
《LINUX设备驱动模型分析之二 总线(BUS)接口分析》中介绍过,不再细说)
- device_driver与bus_type、kobject之间的关联
- 已注册的device_driver类型的变量通过其driver_private类型的成员变量中的knode_bus成员,链接至其依附的总线变量的klist_drivers链表上,并且设置device_driver的成员变量bus指向为其所依附的总线变量;
- 已注册的device_driver类型的变量通过其driver_private类型的成员变量中的kobject变量,将该kobject链接至总线变量的driver_kset中,而总线变量通过其driver_kset变量,实现将所有已注册的设备驱动对应的kobject变量汇聚至一起,这是driver_kset-kobject的关联。
- device_driver类型变量与xxx_device_driver类型变量之间的关联,我们介绍的device_driver变量,在实际使用时,一般会嵌入至具体类型的驱动结构体中,如i2c_driver、platform_driver,以便针对具体类型的驱动,增加该驱动相关的一些特定属性以及接口等。
上面针对driver-kobject-sysfs之间的关联,没有详细说明,下图则详细说明了这三者之间的关联。
- driver与kobject的关联,当注册一个driver时,即会创建一个kobject,用以与sysfs关联
- kobject通过sysfs_drient、sysfs_open_dirent、sysfs_buffer、kobj_type、sysfs_ops,实现了在sysfs目录下创建目录,并为该驱动对应的属性创建sysfs类型的文件。
driver-kobj_type相关说明
在上面的图中,说明了driver-kobj_type,此处稍作说明。针对driver-kobject,其kobj_type为driver_ktype,该结构体定义了所有device-driver的通用sysfs_ops以及driver-koject的释放接口,其定义如下
static struct kobj_type driver_ktype = {
.sysfs_ops = &driver_sysfs_ops,
.release = driver_release,
};
其中driver_release的定义如下,主要是将driver_private类型的内存变量释放。
static void driver_release(struct kobject *kobj)
{
struct driver_private *drv_priv = to_driver(kobj);
pr_debug("driver: '%s': %s