频道栏目
首页 > 资讯 > 其他 > 正文

Linux设备驱动模型框架分析(三)——LDDM的实体bus_type、device和device_driver - CSDN博客

18-07-10        来源:[db:作者]  
收藏   我要投稿

在Linux设备模型中,Bus(总线)是一类特殊的设备,它是连接处理器和其它设备之间的通道(channel)。为了方便设备模型的实现,内核规定,系统中的每个设备都要连接在一个Bus上,这个Bus可以是一个内部Bus、虚拟Bus或者Platform Bus。

device和device driver是Linux驱动开发的基本概念。Linux kernel的思路很简单:驱动开发,就是要开发指定的软件(driver)以驱动指定的设备,所以kernel就为设备和驱动它的driver定义了两个数据结构,分别是device和device_driver

bus_type

内核通过struct bus_type结构,抽象Bus

name,该bus的名称,会在sysfs中以目录的形式存在,如platform bus在sysfs中表现为"/sys/bus/platform”。

dev_name,该名称和下面讲到的struct device结构中的init_name有关。对有些设备而言,允许将设备的名字留空。这样当设备注册到内核后,设备模型的核心逻辑就会用"bus->dev_name+device ID”的形式,为这样的设备生成一个名称。

dev_attrs,被下边的groups取代

bus_groups、dev_groups、drv_groups,一些默认的attribute,可以在bus、device或者device_driver添加到内核时,自动为它们添加相应的attribute。

dev_root,dev_root设备为bus的默认父设备(Default device to use as the parent),但在内核实际实现中,和一个叫sub system的功能有关。

match,一个由具体的bus driver实现的回调函数。当任何属于该Bus的device或者device_driver添加到内核时,内核都会调用该接口,如果新加的device或device_driver匹配上了彼此的话,该接口要返回非零值,此时Bus模块的核心逻辑就会执行后续的处理。

uevent,一个由具体的bus driver实现的回调函数。当任何属于该Bus的device,发生添加、移除或者其它动作时,Bus模块的核心逻辑就会调用该接口,以便bus driver能够修改环境变量。

probe、remove,这两个回调函数,和device_driver中的非常类似,但它们的存在是非常有意义的。可以想象一下,如果需要probe(其实就是初始化)指定的device话,需要保证该device所在的bus是被初始化过、确保能正确工作的。这就要就在执行device_driver的probe前,先执行它的bus的probe。remove的过程相反。

并不是所有的bus都需要probe和remove接口的,因为对有些bus来说(例如platform bus),它本身就是一个虚拟的总线,无所谓初始化,直接就能使用,因此这些bus的driver就可以将这两个回调函数留空。

shutdown、suspend、resume,和probe、remove的原理类似,电源管理相关的实现。

online、offline,和属于这个总线设备的online属性相关。

pm,电源管理相关的逻辑。

iommu_ops,总线的IOMMU相关操作,IOMMU与MMU功能类似,可以给设备一个内核空间的地址(或叫总线地址),而不限于可以直接访问的常规内存区域。

p,一个struct subsys_private类型的指针,kobject隐藏在这个结构后面。这个结构也很重要。

device

 

device结构很复杂,这里将会选一些对理解设备模型非常关键的字段进行说明。

parent,该设备的父设备,一般是该设备所从属的bus、controller等设备。

p,一个用于设备的私有数据结构指针,保存子设备链表,添加父节点,邻居节点和总线链表等。

kobj,该数据结构对应的struct kobject。

init_name,该设备的名称。

在设备模型中,名称是一个非常重要的变量,任何注册到内核中的设备,都必须有一个合法的名称,可以在初始化时给出,也可以由内核根据“bus name + device ID”的方式创造。见bus_type.dev_name的说明。

type,struct device_type结构是新版本内核新引入的一个结构,它和struct device关系,非常类似stuct kobj_type和struct kobject之间的关系。

bus,该device属于哪个总线。

driver,该device对应的device driver。

platform_data,一个指针,用于保存具体的平台相关的数据。linux经常用来保存一些单板相关的数据,来描述包含哪些设备,以及它们如何互联。以便大幅减少BSP的代码量和驱动中ifdef的使用。

power、pm_domain,电源管理相关的逻辑,后续会由电源管理专题讲解。

pins,"PINCTRL”功能。

numa_node,"NUMA”功能。

devt,设备号。在这里,该变量主要用于在sys文件系统中,为每个具有设备号的device,创建/sys/dev/*下的对应目录,如下:

class,该设备属于哪个class。这从侧面说明了class是device的集合。

groups,该设备的默认attribute集合。将会在设备注册时自动在sysfs中创建对应的文件。

device_driver

 

name,该driver的名称。和device结构一样,该名称非常重要,和device和driver的匹配有关。

bus,该driver所驱动设备的总线设备。内核要保证在driver运行前,设备所依赖的总线能够正确初始化。

owner、mod_name,內核module相关的变量。

suppress_bind_attrs,通过sysfs启用bind和unbind的attribute,如下:

# ls /sys/bus/platform/drivers/switch-gpio/

bind uevent unbind

在kernel中,bind/unbind是从用户空间手动的为driver绑定/解绑定指定的设备的机制。

probe、remove,这两个接口函数用于实现driver逻辑的开始和结束。在设备模型的结构下,只有driver和device同时存在时,才需要开始执行driver的代码逻辑。这也是probe和remove两个接口名称的由来:检测到了设备和移除了设备(就是为热拔插起的!)。

shutdown、suspend、resume、pm,电源管理相关的内容。

groups,和struct device结构中的同名变量类似,driver也可以定义一些默认attribute,这样在将driver注册到内核中时,内核设备模型部分的代码会自动将这些attribute添加到sysfs中。

subsys_private

旧的linux存在独立的子系统数据结构subsystem,2.6.35抛弃了这个数据结构。转而用subsys_private表示。

什么是子系统?无论是bus,还是class,还是一些虚拟的子系统,它都构成了一个“子系统(sub-system)”,该子系统会包含形形色色的device或device_driver,就像一个独立的王国一样,存在于内核中。而这些子系统的表现形式,就是/sys/bus(或/sys/class,或其它)目录下面的子目录,每一个子目录,都是一个子系统(如/sys/bus/spi/)。从子系统的角度看bus和后面的class很类似,它们都用subsys_private表示子系统。

subsys、devices_kset、drivers_kset是三个kset。其中subsys,代表了本bus(如/sys/bus/spi),它下面可以包含其它的kset或者其它的kobject;devices_kset和drivers_kset则是bus下面的两个kset(如/sys/bus/spi/devices和/sys/bus/spi/drivers),分别包括本bus下所有的device和device_driver。bus_type与kobject的关系通过subsys成员体现。通过宏to_subsys_private(obj)可以看出。

interface,用于保存该bus下所有的interface。interface抽象了此类子系统的专有功能。

klist_devices、klist_drivers,分别保存了本bus下所有的device和device_driver的指针,以方便查找。

drivers_autoprobe,用于控制该bus下的drivers或者device是否自动probe。

bus、class,分别保存上层的bus或者class指针。
 

device_private

klist_childre,包含此设备所有的子设备。

knode_parent,连入父设备的klist_children时所用的节点。

knode_driver,连入驱动的设备链表所用的节点,driver_private的klist_devices节点。

knode_bus,连入总线的设备链表时所用的节点,subsys_private中klist_devices的节点。

deferred_probe,deferred_probe_list的入口,deferred_probe_list用来重新绑定那些暂时不能获得device全部资源的驱动,这种情况常常是因为某一个驱动需要另一个驱动首先probe。

device,指向包含device_private的device

 

driver_private

kboj,结构对应的kobject。

klist_devices,包含此驱动可以驱动的设备。

knode_bus,连入bus的驱动链表的节点,代表subsys_private中klist_drivers的节点。

mkobj,内核module相关变量。

driver,指向包含driver_private的driver。

 

device_type

name,表示该类型的名称,当该类型的设备添加到内核时,内核会发出"DEVTYPE=‘name’”类型的uevent,告知用户空间某个类型的设备available了。

groups,该类型设备的公共attribute集合。设备注册时,会同时注册这些attribute。这就是面向对象中“继承”的概念。

uevent,所有相同类型的设备,会有一些共有的uevent需要发送,由该接口实现。

release,如果device结构没有提供release接口,就要查询它所属的type是否提供,用于释放device变量所占的空间。

 

bus_type,device和device_driver与kobject的关系

从device和device_driver的角度看

device和device_driver直接继承kobject,bus_type通过subsys_private与kobject发生联系。图中kset和kobject的关系是从kset与包含在它里边的kobject的角度看的,与前面kset与kobjcet的关系角度不同。由此可见,总线、设备和驱动是建立在kobject基础上的,借由kobject和kset建立层次关系。
 

bus_type,device、device_driver的关系

一个device_driver可以支持多个device。bus_type通过subsys_private与device_driver和device发生关联。

bus_type、device、device_driver与sysfs的关系

总线,设备和设备驱动与sysfs的对应关系相对简单直观


相关TAG标签
上一篇:在VMware虚拟机的Ubuntu上配置c/c++编程环境
下一篇:WIN10远程桌面连接步骤:CredSSP加密Oracle修正
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站