新闻资讯
Group news
青岛广盛源肥业有限公司    您的位置: 首页  >  新闻资讯  >  正文

Linux设备模型:Bus

2019年10月12日 文章来源:网络整理 热度:172℃ 作者:刘英

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中表现为"/sys/bus/platform”。

dev_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。

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类似,在"Linux设备模型(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;

14:

15:    struct kset glue_dirs;

16:    struct class *class;

17: };

看到结构内部的字段,就清晰多了,没事不要乱起名字嘛!什么subsys啊,看的晕晕的!不过还是试着先理解一下为什么起名为subsys吧:

上一篇:每个安卓开发初学者应该了解的12个技巧


下一篇:学习Linux操作系统中Alsa音频编程

友情链接
Links