bus, device, driver之间关系

来源:互联网 发布:中俄关系 知乎 编辑:程序博客网 时间:2024/05/29 15:52

总线、设备、驱动,也就是bus、device、driver,在内核里都会有它们自己专属的结构,在include/linux/device.h 里定义。

首先是总线,bus_type.
struct bus_type

{
const char * name;
struct subsystem subsys;   //代表自身
struct kset drivers;            //当前总线的设备驱动集合
struct kset devices;           //所有设备集合
struct klist klist_devices;
struct klist klist_drivers;
struct bus_attribute * bus_attrs;             //总线属性
struct device_attribute * dev_attrs;              //设备属性
struct driver_attribute * drv_attrs;
int (*match)(struct device * dev, structdevice_driver * drv); //设备驱动匹配函数
int (*uevent)(struct device *dev, char **envp,  \
  int num_envp, char *buffer, intbuffer_size);   //热拔插事件
int (*probe)(struct device * dev);
int (*remove)(struct device * dev);
void (*shutdown)(struct device * dev);
int (*suspend)(struct device * dev, pm_message_tstate);
int (*resume)(struct device * dev);
};

下面是设备device的定义:

struct device

{
struct device * parent;      //父设备,一般一个bus也对应一个设备。
struct kobject  kobj;        //代表自身
char bus_id[BUS_ID_SIZE];  
struct bus_type * bus;      /* 所属的总线 */
struct device_driver *driver;    /* 匹配的驱动*/
void *driver_data;                  /* data private to the driver指向驱动 */
void *platform_data;       /* Platform specific data,由驱动定义并使用*/
///更多字段忽略了
};


下面是设备驱动定义:
struct device_driver

{
const char * name;
struct bus_type * bus;//所属总线
struct completion unloaded;
struct kobject  kobj;//代表自身
struct klist       klist_devices;//设备列表
struct klist_node      knode_bus;
struct module * owner;
int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
void (*shutdown) (struct device * dev);
int (*suspend) (struct device * dev,pm_message_t state);
int (*resume) (struct device * dev);
};

 
我们会发现,structbus_type中有成员structksetdriversstructksetdevices

同时structdevice中有两个成员struct bus_type*busstruct device_driver*driver structdevice_driver中有两个成员structbus_type*busstructklistklist_devices

 

structdevice中的bus表示这个设备连到哪个总线上,driver表示这个设备的驱动是什么,structdevice_driver中的bus表示这个驱动属于哪个总线,klist_devices表示这个驱动都支持哪些设备,因为这里device是复数,又是list,更因为一个驱动可以支持多个设备,而一个设备只能绑定一个驱动。当然,structbus_type中的driversdevices分别表示了这个总线拥有哪些设备和哪些驱动。

还有上面device driver结构里出现的kobject结构是什么?kobjectkset都是Linux设备模型中最基本的元素。一般来说应该这么理解,整个Linux的设备模型是一个OO的体系结构,总线、设备和驱动都是其中鲜活存在的对象,kobject是它们的基类,所实现的只是一些公共的接口,kset是同种类型kobject对象的集合,也可以说是对象的容器。

那么总线、设备和驱动之间是如何关联的呢?

先说说总线中的那两条链表是怎么形成的。内核要求每次出现一个设备就要向总线汇报,或者说注册,每次出现一个驱动,也要向总线汇报,或者说注册。比如系统初始化的时候,会扫描连接了哪些设备,并为每一个设备建立起一个structdevice的变量,每一次有一个驱动程序,就要准备一个structdevice_driver结构的变量。把这些变量统统加入相应的链表,device插入devices链表,driver插入drivers链表。这样通过总线就能找到每一个设备,每一个驱动。

设备和驱动又是如何联系?

原来是把每一个要用的设备在计算机启动之前就已经插好了,插放在它应该在的位置上,然后计算机启动,然后操作系统开始初始化,总线开始扫描设备,每找到一个设备,就为其申请一个structdevice结构,并且挂入总线中的devices链表中来,然后每一个驱动程序开始初始化,开始注册其struct device_driver结构,然后它去总线的devices链表中去寻找(遍历),去寻找每一个还没有绑定驱动的设备,structdevice中的structdevice_driver指针仍为空的设备,然后它会去观察这种设备的特征,看是否是他所支持的设备,如果是,那么调用一个叫做device_bind_driver的函数,然后他们就结为了秦晋之好。换句话说,把structdevice中的structdevice_driverdriver指向这个驱动,而struct device_driver driverstruct device加入他的那structklist klist_devices链表中来。就这样,busdevicedriver,这三者之间或者说他们中的两两之间,就给联系上了。知道其中之一,就能找到另外两个。

但现在情况变了,出现了一种新的名词,叫热插拔。设备可以在计算机启动以后在插入或者拔出计算机了。设备可以在任何时刻出现,而驱动也可以在任何时刻被加载,所以,出现的情况就是,每当一个structdevice诞生,它就会去busdrivers链表中寻找自己的另一半,反之,每当一个struct device_driver诞生,它就去busdevices链表中寻找它的那些设备。如果找到了合适的,那么OK,和之前那种情况一下,调device_bind_driver绑定好。如果找不到,没有关系,等待吧!