Linux设备模型:Bus.doc
《Linux设备模型:Bus.doc》由会员分享,可在线阅读,更多相关《Linux设备模型:Bus.doc(11页珍藏版)》请在三一文库上搜索。
1、Linux设备模型:Bus1. 概述在Linux设备模型中,Bus(总线)是一类特殊的设备,它是连接处理器和其它设备之间的通道(channel)。为了方便设备模型的实现,内核规定,系统中的每个设备都要连接在一个Bus上,这个Bus可以是一个内部Bus、虚拟Bus或者Platform Bus。内核通过struct bus_type结构,抽象Bus,它是在include/linux/device.h中定义的。本文会围绕该结构,描述Linux内核中Bus的功能,以及相关的实现逻辑。最后,会简单的介绍一些标准的Bus(如Platform),介绍它们的用途、它们的使用场景。2. 功能说明按照老传统,描述
2、功能前,先介绍一下该模块的一些核心数据结构,对bus模块而言,核心数据结构就是struct bus_type,另外,还有一个sub system相关的结构,会一并说明。2.1 struct bus_type1: /* inlcude/linux/device.h, line 93 */2: struct bus_type 3: const char *name;4: const char *dev_name;5: struct device *dev_root;6: struct bus_attribute *bus_attrs;7: struct device_attribute *dev_
3、attrs;8: struct driver_attribute *drv_attrs;9:10:int (*match)(struct device *dev, struct device_driver *drv);11:int (*uevent)(struct device *dev, struct kobj_uevent_env *env);12:int (*probe)(struct device *dev);13:int (*remove)(struct device *dev);14:void (*shutdown)(struct device *dev);15:16:int (*
4、suspend)(struct device *dev, pm_message_t state);17:int (*resume)(struct device *dev);18:19:const struct dev_pm_ops *pm;20:21:struct iommu_ops *iommu_ops;22:23:struct subsys_private *p;24:struct lock_class_key lock_key;25: ;name,该bus的名称,会在sysfs中以目录的形式存在,如platform bus在sysfs中表现为/sys/bus/platform”。dev_
5、name,该名称和Linux设备模型(5)_device和device driver”所讲述的struct device结构中的init_name有关。对有些设备而言(例如批量化的USB设备),设计者根本就懒得为它起名字的,而内核也支持这种懒惰,允许将设备的名字留空。这样当设备注册到内核后,设备模型的核心逻辑就会用bus-dev_name+device ID”的形式,为这样的设备生成一个名称。bus_attrs、dev_attrs、drv_attrs,一些默认的attribute,可以在bus、device或者device_driver添加到内核时,自动为它们添加相应的attribute。de
6、v_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的d
7、evice,发生添加、移除或者其它动作时,Bus模块的核心逻辑就会调用该接口,以便bus driver能够修改环境变量。probe、remove,这两个回调函数,和device_driver中的非常类似,但它们的存在是非常有意义的。可以想象一下,如果需要probe(其实就是初始化)指定的device话,需要保证该device所在的bus是被初始化过、确保能正确工作的。这就要就在执行device_driver的probe前,先执行它的bus的probe。remove的过程相反。注1:并不是所有的bus都需要probe和remove接口的,因为对有些bus来说(例如platform bus),它本
8、身就是一个虚拟的总线,无所谓初始化,直接就能使用,因此这些bus的driver就可以将这两个回调函数留空。shutdown、suspend、resume,和probe、remove的原理类似,电源管理相关的实现,暂不说明。pm,电源管理相关的逻辑,暂不说明。iommu_ops,暂不说明。p,一个struct subsys_private类型的指针,后面我们会用一个小节说明。2.2 struct subsys_private该结构和device_driver中的struct driver_private类似,在Linux设备模型(5)_device和device driver”章节中有提到它,但
9、没有详细说明。要说明subsys_private的功能,让我们先看一下该结构的定义:1: /* drivers/base/base.h, line 28 */2: struct subsys_private 3: struct kset subsys;4: struct kset *devices_kset;5: struct list_head interfaces;6: struct mutex mutex;7:8: struct kset *drivers_kset;9: struct klist klist_devices;10:struct klist klist_drivers;1
10、1:struct blocking_notifier_head bus_noTIfier;12:unsigned int drivers_autoprobe:1;13:struct bus_type *bus;14:15:struct kset glue_dirs;16:struct class *class;17: ;看到结构内部的字段,就清晰多了,没事不要乱起名字嘛!什么subsys啊,看的晕晕的!不过还是试着先理解一下为什么起名为subsys吧:按理说,这个结构就是集合了一些bus模块需要使用的私有数据,例如kset啦、klist啦等等,命名为bus_private会好点(就像devic
11、e_driver模块一样)。不过为什么内核没这么做呢?看看include/linux/device.h中的struct class结构(我们会在下一篇文章中介绍class)就知道了,因为class结构中也包含了一个一模一样的struct subsys_private指针,看来class和bus很相似啊。想到这里,就好理解了,无论是bus,还是class,还是我们会在后面看到的一些虚拟的子系统,它都构成了一个“子系统(sub-system)”,该子系统会包含形形色色的device或device_driver,就像一个独立的王国一样,存在于内核中。而这些子系统的表现形式,就是/sys/bus(或/
12、sys/class,或其它)目录下面的子目录,每一个子目录,都是一个子系统(如/sys/bus/spi/)。好了,我们回过头来看一下struct subsys_private中各个字段的解释:subsys、devices_kset、drivers_kset是三个kset,由Linux设备模型(2)_Kobject”中对kset的描述可知,kset是一个特殊的kobject,用来集合相似的kobject,它在sysfs中也会以目录的形式体现。其中subsys,代表了本bus(如/sys/bus/spi),它下面可以包含其它的kset或者其它的kobject;devices_kset和driver
13、s_kset则是bus下面的两个kset(如/sys/bus/spi/devices和/sys/bus/spi/drivers),分别包括本bus下所有的device和device_driver。interface是一个list head,用于保存该bus下所有的interface。有关interface的概念后面会详细介绍。klist_devices和klist_drivers是两个链表,分别保存了本bus下所有的device和device_driver的指针,以方便查找。drivers_autoprobe,用于控制该bus下的drivers或者device是否自动probe,Linux设备
14、模型(5)_device和device driver”中有提到。bus和class指针,分别保存上层的bus或者class指针。2.3 功能总结根据上面的核心数据结构,可以总结出bus模块的功能包括:bus的注册和注销本bus下有device或者device_driver注册到内核时的处理本bus下有device或者device_driver从内核注销时的处理device_drivers的probe处理管理bus下的所有device和device_driver3. 内部执行逻辑分析3.1 bus的注册bus的注册是由bus_register接口实现的,该接口的原型是在include/linux
15、/device.h中声明的,并在drivers/base/bus.c中实现,其原型如下:1: /* include/linux/device.h, line 118 */2: extern int _must_check bus_register(struct bus_type *bus);该功能的执行逻辑如下:为bus_type中struct subsys_private类型的指针分配空间,并更新priv-bus和bus-p两个指针为正确的值初始化priv-subsys.kobj的name、kset、ktype等字段,启动name就是该bus的name(它会体现在sysfs中),kset和k
16、type由bus模块实现,分别为bus_kset和bus_ktype调用kset_register将priv-subsys注册到内核中,该接口同时会向sysfs中添加对应的目录(如/sys/bus/spi)调用bus_create_file向bus目录下添加一个uevent attribute(如/sys/bus/spi/uevent)调用kset_create_and_add分别向内核添加devices和device_drivers kset,同时会体现在sysfs中初始化priv指针中的mutex、klist_devices和klist_drivers等变量调用add_probe_file
17、s接口,在bus下添加drivers_probe和drivers_autoprobe两个attribute(如/sys/bus/spi/drivers_probe和/sys/bus/spi/drivers_autoprobe),其中drivers_probe允许用户空间程序主动出发指定bus下的device_driver的probe动作,而drivers_autoprobe控制是否在device或device_driver添加到内核时,自动执行probe调用bus_add_attrs,添加由bus_attrs指针定义的bus的默认attribute,这些attributes最终会体现在/sys
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 设备 模型 Bus
链接地址:https://www.31doc.com/p-3255495.html