从Linux内核设计者的角度看 - 设备驱动的架构设计
Linux中的设备驱动概念中的设备和驱动指的是啥?
直接说设备驱动其实是比较抽象的,举个例子就特别明了了,比如我们要控制1个led的亮灭,那么led就是设备,控制led运行的软件就是该设备的驱动。也就是说,这里的设备就是现实中的一个电子设备,设备驱动就是控制这个电子设备运行的软件程序。
在现实生活中,有成千上万种电子设备,Linux要做到所有设备的兼容运行,就需要一套行之有效的设备驱动架构,那么,Linux是如何做的呢?
Linux的设备驱动架构叫做 总线-设备-驱动模型。无论什么电子设备,都需要通过某种总线让cpu访问才能进行控制,总线的类型是有限的,因此,Linux设计了一套以总线为核心的设备驱动架构。
Linux首先将总线进行了抽象 -- struct bus_type ,这样就可以用它来设计各种各样的总线了,最常见的就是i2c和spi总线了,这俩都是外设总线,其实还有一个特殊的总线叫做平台总线(platform bus),对应的设备叫平台设备,还是以之前的led为例,要想操作led,实质上需要操作的是led连在芯片上的gpio口,而gpio是由芯片里面的gpio控制器所控制的,也就是说,led的控制需要2个驱动,1个是gpio控制器的驱动,1个是led的驱动,led和gpio控制器通过gpio连接,gpio就可以看作是一种总线;那gpio控制器是如何控制的,显然gpio控制器属于芯片的一部分,通过芯片内部的总线连接,可以通过寄存器直接访问,这一类通过寄存器直接访问的设备就北叫做平台设备,连接的总线也就叫做平台总线。
struct bus_type {
const char *name;
const char *dev_name;
struct device *dev_root;
const struct attribute_group **bus_groups;
const struct attribute_group **dev_groups;
const struct attribute_group **drv_groups;
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
void (*sync_state)(struct device *dev);
void (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*online)(struct device *dev);
int (*offline)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
int (*num_vf)(struct device *dev);
int (*dma_configure)(struct device *dev);
const struct dev_pm_ops *pm;
const struct iommu_ops *iommu_ops;
struct subsys_private *p;
struct lock_class_key lock_key;
bool need_parent_lock;
};