uevent 驱动_LINUX设备驱动模型分析之二 总线(BUS)接口分析

本文深入分析Linux设备驱动模型中的总线接口,包括bus_type、bus_attribute等结构体,以及总线注册、注销接口。文章阐述了如何通过这些接口实现设备与驱动的关联、sysfs文件系统的映射,并探讨了bus_attribute、device_attribute和driver_attribute结构体的作用。
摘要由CSDN通过智能技术生成

上一章我们对LINUX设备模型的概念进行了分析,也大概理清了bus、class、device、drivers之间的关联与区别,本章开始我们就进行具体概念的分析,首先分析总线的概念以及总线接口分析。在进行分析之前我们还是把上一章中的bus-device-drivers的关联图放上来,通过该图我们对总线接口的实现也会有一个大概的轮廓,即每一个具体的总线均包括设备与驱动两部分,而每一个具体总线的所有添加的设备均链接至device下,每一个总线的所有注册的驱动均链接至drivers,而bus接口所有实现的功能也可以大致分为总线的注册、设备的注册、驱动的注册这三个部分。因此本章也从这几个方面进行分析。

cc1f736fab73a309b78b8336b130361f.png

总线相关的结构体介绍

与总线相关的结构体主要包括bus_type、bus_attribute、device、driver、device_attribute、driver_attribute、

subsys_private、kset、kobject等,其中kset、kobject、subsys_private结构体我们之前已经介绍过,此处不再细说。

struct bus_type接口说明

该接口定义如下,

e3ff1f0c8ac83869f40bc8057bf2627c.png

该结构体定义的目的也是实现上述bus-device-driver之间的关联,同时也与kobject、kset关联,进而实现与sysfs的关联。具体说明如下:一、bus-device-driver关联通过struct subsys_private类型的变量p,定义了device、driver对应的kset变量,完成将所有设备、驱动对应的kobject;

  1. 通过struct subsys_private类型的变量p,定义了device、driver对应的链表,将所有该总线注册或添加的驱动与设备链接在一起,实现上面图中所描述的bus-device-driver关联

二、总线自身属性以及与kobject、sysfs的关联

  1. 通过bus_attribute类型的变量,定义总线自身的属性参数(通过sysfs中的接口,完成sysfs文件的创建,并提供该属性的读写接口store/show等);
  2. 通过device_attribute类型的变量,完成该bus总线默认的设备属性参数(这些参数为该总线下每一个设备均包含的属性,通过sysfs中的接口,完成sysfs文件的创建,并提供该属性的读写接口store/show等);
  3. 通过driver_attribute类型的变量,完成该bus总线默认的驱动属性参数(这些参数为该总线下每一个驱动均包含的属性,通过sysfs中的接口,完成sysfs文件的创建,并提供该属性的读写接口store/show等);
  4. struct subsys_private类型的变量p,定义了该总线对应的kobject变量,从而为该bus总线在sysfs文件系统下创建该bus对应的目录,并借助该kobject->kref变量,提供针对该总线的引用计数;

三、总线相关的处理接口

  1. match接口完成总线中设备与驱动的匹配检测,匹配上的设备与驱动即完成绑定操作;
  2. probe接口,当设备与驱动匹配后,则调用总线的probe接口,进行设备的probe操作(该接口一般会调用驱动的probe接口,进行探测操作);
  3. remove接口,当移除驱动时,即会调用总线的remove接口,进行申请的remove操作(该接口一般会调用驱动的remove接口,进行移除操作);

struct bus_attribute结构体说明

该结构体通过包含通用属性结构体变量attr和store/show接口,实现针对bus类型属性的读写接口。

d9b5a86f0c59da56b47153c201566acb.png
05eedb0697b3048bf50a47e066a58c0e.png

为了理清该结构体变量与kobject、sysfs等的关联,特将它们之间的关联图画出。在调用总线注册接口bus_register时,会创建该bus总线默认的属性文件,并设置该bus总线对应kobject的kobj_type,而kobj_type中的操作接口指针即为 bus_sysfs_ops,其提供针对bus属性的通用读写接口,而创建的bus属性变量中,针对具体的属性定义特定接口,由bus_sysfs_ops中的读写接口调用。

其中的关联说明如下:

  1. 图中的kset对应bus_type->p->subsys,而kset中的kobject包含了引用计数以及kobj_type;
  2. 根据bus_type->p->subsys,通过调用sysfs中的kset_register,实现kset初始化,并根据其kobject变量在sysfs中创建目录,并调用sysfs_create_file将该bus相关的默认属性在sysfs中创建对应的文件;
  3. 应用层若要访问bus属性,则通过系统调用open、read、write接口,最终调用sysfs中注册的文件操作接口sysfs_open_file、sysfs_read_file、sysfs_write_file,最终调用bus_attribute中store/show接口(这块具体的实现可参考《

LINUX SYSFS文件系统分析之四 文件处理及相关系统调用分析》)。

上图没有画出文件描述符、VFS中dentry、inode节点与之的关联,在《

LINUX SYSFS文件系统分析之四 文件处理及相关系统调用分析》中有详尽的描述。

此处关联图是针对bus_type本身的kset、kobject、bus_attribute、sysfs_dirent、kobj_type、sysfs_ops的关联,而在bus_register时,也就是完成这些结构体类型变量之间的关联,实现bus目录、bus属性等在sysfs中表示,我们理解了下面这张图基本上也就属性了bus总线相关的功能了。

而针对bus总线对应kobject的通用kobj_type定义以及其sysfs_ops定义如下所示

e5863f22c59a9dfa35119fe1eb4f8b50.png

struct device_attribute 结构体说明

该结构体的定义如下,其定义实现与bus_attribute类似,而在bus_type->dev_attrs中定义的默认属性,属于添加到该总线上的所有设备的默认属性,即每一个添加到该总线上的设备,其对应kobject上均会包含这些默认属性。

a74d93a876a3e6754eba596dece79f66.png

在进行bus_add_device接口时,除了创建设备对应的kobject外,还会将该kobject链接到bus_type->klist_devices的list上,同时会调用sysfs_create_file将默认属性在该device对应目录下创建sysfs文件,其处理流程和上面bus_attribute类似,唯一不同的是此时创建的kobject是链接的kset->list上,而不是kset->kobj的,如下图所示。

b8caea28a432d4185dc7e6599b2cd017.png

针对device设备而言,其kobject对应的默认kobj_type以及默认通用sysfs_ops的定义如下

2d3f4b7fa7680cc8b647adbfb0937cac.png

struct driver_attribute 结构体说明

该结构体的定义与device_attribute类似,在bus_type->drv_attrs中定义的默认属性,属于添加到该总线上的所有设备的默认属性,即每一个添加到该总线上的设备,其对应kobject上均会包含这些默认属性。

在bus_add_driver中会进行driver的添加以及对应kobject、driver_attribute对应属性文件的创建等信息,其流程图与上面device的处理流程类似,此处不再赘述。

1a6515881924e44a7fa1aa706d96f37e.png

上面分析了bus相关的结构体变量(没有分析struct device 、struct device_driver变量,后面分析),下面就开始进行相关接口的分析操作,主要设置bus注册、注销、bus模块初始化、设备添加到总线、驱动添加到总线上等。

总线模块初始化接口分析

该接口主要通过调用kset_create_and_add接口创建一个kset类型的变量bus_kset,并在sysfs的根目录下创建bus名称的目录(该接口的实现也比较简单,流程图如下所示,而关于kset_create_and_add接口的实现,可参考文件《LINUX SYSFS文件系统分析之五 kobject、kset相关接口分析》)。该kset变量会作为bus子模块的父目录,同时也会将所有注册的bus类型变量汇聚在一起,而bus_kset与各具体bus的kset的关联如下下图所示,通过kset->list将所有已注册的xxx_bus_kset变量链接在一起。

a48c6e9cc7749204d9f5bd2a4cbd2466.png
1cb41360eb633bbd20cdbbc14c77147e.png

总线注册与注销接口分析说明

总线注册接口bus_register

总线注册接口的流程图如下,其实结合上面的结构体分析,我们也可以大概总结出总线注册接口所实现的功能,下面我们详细分析之。

  1. 创建subsys_private类型的变量,赋值给该bus变量的subsys_private类型的成员变量p;
  2. 设置bus总线对应的kset、kobject,并调用kset_register接口在sysfs文件系统的/bus/目录下创建该bus子目录,并将该bus对应的kobject链接到全局变量bus_kset的链表中;
  3. 调用bus_create_file接口,为该bus默认的bus_uevent属性创建对应的sysfs文件;
  4. 调用kset_create_and_add为该bus创建kset类型的devices_kset、drivers_kset,并在该bus目录下创建对应的devices、drivers 的sysfs子目录,而这两个变量,分别用于将注册到该总线上的所有设备、驱动链接在一起;
  5. 调用add_probe_files、bus_add_attrs接口,创建该bus相关的bus_attr_drivers_probe、
93a5101801684302d71684af2fe29ad5.png

bus_attr_drivers_autoprobe以及该bus默认属性bus_attrs对应的sysfs文件等。

至此,即完成了bus类型的注册。而针对bus注册相关的bus_ktype接口,其定义如下,主要为bus_ktype、bus_sysfs_ops的定义,针对bus_sysfs_ops为bus总线属性读写的通用接口,在上面bus_attribute结构体的定义中,也进行了详细说明,bus_ktype、bus_sysfs_ops与kobject以及sysfs模块相关的结构体结合后,即完成了针对bus属性相关的系统调用关联(关于关联过程,具体具体可参考 《LINUX SYSFS文件系统分析之四 文件处理及相关系统调用分析》)

f921dffb8774ea18e9ab5c113abef898.png

总线注销接口bus_unregister

针对该接口,主要就是bus_register中的相反操作,通过调用kset_unregister、bus_remove_file、bus_remove_attrs、device_unregister以及kfree接口实现针对bus_register中注册的kset以及创建的sysfs文件的remove操作,同时释放在bus_register中申请的subsys_private类型的内存空间。

至此完成了总线注册与注销接口的分析,而针对bus_add_device、bus_add_driver接口的分析以及device_add、device_init等接口的实现分析,将在后面的章节中介绍与说明。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值