总线,设备,和驱动的关联

嵌入式系统 时间:2016-12-08来源:网络

  Linux设备模型中三个很重要的概念就是总线,设备,驱动.即bus,device,driver,而实际上内核中也定义了这么一些数据结构,他们是 struct bus_type,struct device,struct device_driver,这三个重要的数据结构都来自一个地方,include/linux/device.h.我们知道总线有很多种,pci总线,scsi总线,usb 总线,所以我们会看到 Linux 内核代码中出现pci_bus_type,scsi_bus_type,usb_bus_type,他们都是struct bus_type类型的变量.而struct bus_type结构中两个非常重要的成员就是 struct kset drivers 和 struct kset devices.kset 和另一个叫做 kobject正是 Linux Kernel 2.6中设备模型的基本元素,但此处我们却不愿多讲,因为暂时不用去认识他们.我们的生命中会遇见许许多多的人和事,但更多的人和事与我们只是擦肩而过,只是我们生命中的过客而已.在我们人生的电影中,他们也许只有一个镜头,甚至那一个镜头后来也被剪辑掉了.这里我们只需要知道,drivers 和 devices 的存在,让struct bus_type与两个链表联系了起来,一个是 devices 的链表,一个是drivers 的链表,也就是说,知道一条总线所对应的数据结构,就可以找到这条总线所关联的设备有哪些,又有哪些支持这类设备的驱动程序.

  而要实现这些,就要求每次出现一个设备就要向总线汇报,或者说注册,每次出现一个驱动,也要向总线报,或者说注册.比如系统初始化的时候,会扫描连接了哪些设备,并为每一个设备建立起一个 struct device的变量,每一次有一个驱动程序,就要准备一个 struct device_driver结构的变量.把这些变量统统加入相应的链表,device插入devices链表,driver插入drivers链表. 这样通过总线就能找到每一个设备,每一个驱动.

  然而,假如计算机里只有设备却没有对应的驱动,那么设备无法工作.反过来,倘若只有驱动却没有设备,驱动也起不了任何作用.在他们遇见彼此之前,双方都如同路埂的野草,一个飘啊飘,一个摇啊摇,谁也不知道未来在哪里,只能在生命的风里飘摇.于是总线上的两张表里就慢慢的就挂上了那许多孤单的灵魂.devices 开始多了,drivers 开始多了,他们像是两个来自世界,devices 们彼此取暖,drivers 们一起狂欢,但他们有一点是相同的,都只是在等待属于自己的那个另一半.

  看代码的我,一直好奇的想知道,他们是否和我们现实中一样,有些人注定是等别人,而有些人是注定被人等的.

  struct bus_type中为 devices 和 drivers 准备了两个链表,而代表 device的结构体struct device中又有两个成员,struct bus_type *bus 和struct device_driver *driver,同样,代表driver 的结构体 struct device_driver同样有两个成员,struct bus_type *bus和 struct list_head devices,struct device和 struct device_driver的定义和 struct bus_type一样,在 include/linux/device.h 中.凭一种男人的直觉,可以知晓,struct device中的 bus记录的是这个设备连在哪条总线上,driver记录的是这个设备用的是哪个驱动,反过来,struct device_driver中的bus代表的也是这个驱动属于哪条总线,devices记录的是这个驱动支持的那些设备,没错,是devices(复数),而不是device(单数),因为一个驱动程序可以支持一个或多个设备,反过来一个设备则只会绑定给一个驱动程序.

  于是我们想知道,关于 bus,关于 device,关于 driver,他们是如何建立联系的呢?换言之,这三个数据结构中的指针是如何被赋值的?绝对不可能发生的事情是,一旦为一条总线申请了一个struct bus_type的数据结构之后,它就知道它的devices链表和drivers链表会包含哪些东西,这些咚咚一定不会是先天就有的,只能是后天填进来的.而具体到usb 系统,完成这个工作的就是usb core.usb core的代码会进行整个 usb 系统的初始化,比如申请struct bus_type usb_bus_type,然后会扫描 usb 总线,看线上连接了哪些usb设备,或者说 root hub上连了哪些usb设备,比如说连了一个usb键盘,那么就为它准备一个struct device,根据它的实际情况,为这个struct device赋值,并插入devices链表中来.又比如root hub上连了一个普通的hub,那么除了要为这个hub 本身准备一个 struct device以外,还得继续扫描看这个 hub上是否又连了别的设备,有的话继续重复之前的事情,这样一直进行下去,直到完成整个扫描,最终就把

  usb_bus_type中的 devices链表给建立了起来. 那么 drivers链表呢?这个就不用bus方面主动了,而该由每一个 driver 本身去 bus上面登记,或者说挂牌。

  bus上的两张链表记录了每一个device和driver,那么device和driver这两者之间又是如何联系起来的

  呢?此刻,必须抛出这样一个问题,先有device还是 driver?

  很久很久以前,在那激情燃烧的岁月里,先有的是device,每一个要用的device在计算机启动之前就已经插

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

  但现在情况变了,在这红莲绽放的日子里,在这樱花伤逝的日子里,出现了一种新的名词,叫热插拔.device

  可以在计算机启动以后在插入或者拔出计算机了.因此,很难再说是先有device还是先有driver了.因为都有可能.device可以在任何时刻出现,而driver也可以在任何时刻被加载,所以,出现的情况就是,每当一个

  struct device诞生,它就会去bus 的drivers链表中寻找自己的另一半,反之,每当一个一个struct

  device_driver诞生,它就去bus的devices链表中寻找它的那些设备.如果找到了合适的,那么ok,和之前

  那种情况一下,调用device_bind_driver绑定好.如果找不到,没有关系,等待吧,等到昙花再开,等到风景看

  透,心中相信,这世界上总有一个人是你所等的,只是还没有遇到而已.

关键词: 总线 驱动

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章


用户评论

请文明上网,做现代文明人
验证码:
查看电脑版