Linux 总线、设备与设备驱动的关系

      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上的两张链表记录了每一个devicedriver,那么devicedriver这两者之间又是如何联系起来的呢此刻,必须抛出这样一个问题,先有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绑定好。如果找不到,没有关系,等待吧,等到昙花再开,等到风景看透,心中相信,这世界上总有一个人是你所等的,只是还没有遇到而已。

 


我们团队有着十几年的期货程序化交易算法与软件研发经验,基于C++ Qt技术研发了具有自主知识产权的期货智能程序化交易一体化系统平台,该平台封装了二百多个量化指标,具有低时延、高性能、小滑点、可定制和跨平台的特点。团队致力于将人工智能技术与传统的程序化交易技术相结合为客户提供灵活可定制的期货智能程序化交易服务和产品。

       

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值