Linux设备模型:Bus 下载本文

内容发布更新时间 : 2024/9/20 23:33:14星期一 下面是文章的全部内容请认真阅读。

Linux设备模型:Bus

1. 概述

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

内核通过struct bus_type结构,抽象Bus,它是在include/linux/device.h中定义的。本文会围绕该结构,描述Linux内核中Bus的功能,以及相关的实现逻辑。最后,会简单的介绍一些标准的Bus(如Platform),介绍它们的用途、它们的使用场景。 2. 功能说明

按照老传统,描述功能前,先介绍一下该模块的一些核心数据结构,对bus模块而言,核心数据结构就是struct bus_type,另外,还有一个sub system相关的结构,会一并说明。 2.1 struct bus_type

1: /* 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_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 (*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中表现为\”。

dev_name,该名称和\设备模型(5)_device和device driver”所讲述的struct device结构中的init_name有关。对有些设备而言(例如批量化的USB设备),设计者根本就懒得为它起名字的,而内核也支持这种懒惰,允许将设备的名字留空。这样当设备注册到内核后,设备模型的核心逻辑就会用\ID”的形式,为这样的设备生成一个名称。

bus_attrs、dev_attrs、drv_attrs,一些默认的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的过程相反。 注1:并不是所有的bus都需要probe和remove接口的,因为对有些bus来说(例如platform bus),它本身就是一个虚拟的总线,无所谓初始化,直接就能使用,因此这些bus的driver就可以将这两个回调函数留空。

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

pm,电源管理相关的逻辑,暂不说明。 iommu_ops,暂不说明。

p,一个struct subsys_private类型的指针,后面我们会用一个小节说明。 2.2 struct subsys_private

该结构和device_driver中的struct driver_private类似,在\设备模型(5)_device和device driver”章节中有提到它,但没有详细说明。

要说明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;

11: struct blocking_notifier_head bus_noTIfier; 12: unsigned int drivers_autoprobe:1; 13: struct bus_type *bus;