前面几篇文章我们对bus-device-driver模型进行了单独介绍,本篇文章我们对这三部分进行总结,同时对之前文章中未细化的部分进行详细说明。
bus-device-driver相关结构体关联
如下图是包含bus-device-driver的关联图,我们根据该流程图再次进行一下说明。
1.devices_kset集合说明
内核系统中在device模块的初始化接口中,创建了一个kset类型的全局变量devices_kset
该kset类型的全局变量,通过list成员集合了所有系统中已创建的device类型对应的kobject变量,
系统中依附在所有类型总线上的device,均会通过其对应的kobject变量,链接至devices_kset链表上。即通过devices_kset可找到系统中所有已创建的device。这一层关系和具体的bus-device-driver绑定没有关联。
2.bus_kset集合说明
内核系统中在bus模块初始化接口中,创建了一个kset类型的全局变量bus_kset。该全局变量
会将系统中所有已注册的总线类型对应的kobject链接在一起,通过该系统变量可以查看系统中所有已注册的总线类型。
3.bus->p->driver_kset集合说明
该变量和以上两个全局变量略有不同,该变量依附于具体的总线类型,仅在具体的总线变量创建时,方会创建该变量,该变量会将所有注册进其依附总线的驱动对应的kobject链接在一起。
4.bus->p->device_kset集合说明
该变量主要是总线变量的成员变量,系统中主要使用该kset对应的kobject以及与具体设备变量对应的kobject,这两个kobject相互创建链接子目录。(针对bus->p->device_kset与device类型变量对应的kobject的链接关系,没有在上面图中画出)
5.bus->p->klist_devices
该变量主要用于将所有注册至该总线上的device类型变量链接在一起,通过该变量可以查看该总线上当前已注册的设备。
6.bus->p->klist_drivers
该变量主要用于将所有注册至该总线上的device_driver类型变量链接在一起,通过该变量可以查看该总线上当前已注册的驱动。
总线类型通过klist_devices、klist_drivers,可以找到该总线上所有已注册的设备与驱动
7.device_driver->p->klist_devices
该变量主要用于链接所有已和该驱动绑定的设备,当进行设备与驱动的绑定或者解绑前,可通过遍历该链表确认执行操作的设备是否已在绑定列表中。
bus-device-driver的一些说明
下面我们主要是针对bus-device-driver再进行一些补充说明。
bus-device-driver的绑定操作
- 当系统中完成一个device的注册时,当完成device-bus相关的绑定(包括device、bus_type、kobject等绑定),会遍历该总线上所有已注册的驱动(通过遍历链表bus->p->klist_drivers实现),若该device与已注册的驱动匹配(如设备名称与驱动名称匹配等,匹配函数一般由总线类型变量中的match函数指针提供,如platform总线的match函数为platform_match),则再完成device-driver的绑定操作,并调用驱动的probe函数,完成对device的探测。对应函数为bus_probe_device、device_attach、__device_attach、driver_bound等。
- 当系统中完成一个driver的注册时,在完成driver-bus相关的绑定后,也会遍历该总线上所有已注册的设备(通过遍历链表bus->p->klist_devices实现),针对未进行device-driver绑定的设备,若device与该driver匹配,则完成device-driver的绑定操作,并调用驱动的probe函数,完成对device的探测。对应函数为driver_attach、__driver_attach、driver_probe_device、driver_bound等。
这也是总线变量中的klist_drivers、klist_devices变量的作用。
- 针对device结构体、driver结构体,一般会被嵌入更大的结构体中,用以实现具体总线类型的设备与驱动,如platform总线(platform_device、platform_driver)、i2c总线(i2c_client、i2c_driver、i2c_adapter)、pci总线(pci_dev、pci_driver)等。
而针对总线注册与注销接口、设备注册与注销接口、驱动注册与注销接口,也就是进行上面所说的关联罢了。
设备与驱动绑定时的探测接口调用
当设备与驱动完成绑定时,会调用对应的探测接口,进行设备的初始化操作,如下即为探测接口的调用关系以及与bus、driver的关系。
如下图所示,当调用device_register、driver_register接口进行设备与驱动的注册时,若设备与驱动匹配后,则调用总线的probe接口或者driver的probe接口进行探测。
通过总线的probe接口,最终也是调用driver->probe接口进行探测。而针对driver->probe
接口,最终会调用具体driver->probe(如platform_driver->probe、i2c_driver->probe、sp_driver->probe等),从driver->probe到xxx_driver->probe接口的调用,其实就是面向对象中的通过调用基类的接口,从而实现调用子类的接口。
设备与驱动解绑时的去除接口调用
当设备与驱动完成解绑时,会调用对应的remove接口,进行设备的移除时的处理操作,如下即为remove接口的调用关系以及与bus、driver的关系。
如下图所示,当调用device_unregister、driverun_register接口进行设备的移除操作,通过调用总线的probe接口或者driver的probe接口进行移除操作。remove的流程与上面的probe流程类似,这个也是内核面向对象实现的一种。
对象的生命周期
我们知道kset、device、driver、bus_type类型的变量,均使用kobject->kref作为引用计数
使用,而针对kobject的释放也是通过该引用计数实现,当引用计数为0时,则释放该kobject,同时也会根据kobject->kobj_type->sysfs_ops->release接口,实现对kobject所嵌入的内存的释放操作。其处理流程如下所示
而针对kobject->kobj_type而言,针对bus_type,其定义如下,release接口为device_release;针对bus_type,其对应kobj_type定义如下,并没有为bus_type创建特定的release接口。
至此我们完成了设备驱动模型(bus-device-driver)的分析,下一篇文章我们将以platform总线为主介绍具体的总线及其设备与驱动的实现。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/10113.html