• Linux内核(8)


    设备模型拍得再玄幻,它也只是个模型,必须得落实在具体的子系统,否则就只能抱着个最佳技术奖空遗恨。既然前面已经以USB子系统的实现分析示例了分析内核源码应该如何入手,那么这里就仍然以USB子系统为例,看看设备模型是如何软着陆的。

    内核中USB子系统的结构

    我们已经知道了USB子系统的代码都位于drivers/usb目录下面,也认识了一个很重要的目录——core子目录。现在,我们再来看一个很重要的模块——usbcore。你可以使用“lsmod”命令看一下,在显示的结果里能够找到有一个模块叫做usbcore。

    localhost:/usr/src/linux-2.6.23/drivers/usb/core # lsmod
    Module                  Size  Used by
    af_packet              55820  2
    raw                    89504  0
    nfs                   230840  2
    lockd                  87536  2 nfs
    nfs_acl                20352  1 nfs
    sunrpc                172360  4 nfs,lockd,nfs_acl
    ipv6                  329728  36
    button                 24224  0
    battery                27272  0
    ac                     22152  0
    apparmor               73760  0
    aamatch_pcre           30720  1 apparmor
    loop                   32784  0
    usbhid                 60832  0
    dm_mod                 77232  0
    ide_cd                 57120  0
    hw_random              22440  0
    ehci_hcd               47624  0
    cdrom                  52392  1 ide_cd
    uhci_hcd               48544  0
    shpchp                 61984  0
    bnx2                  157296  0
    usbcore               149288  4 usbhid,ehci_hcd,uhci_hcd
    e1000                 130872  0
    pci_hotplug            44800  1 shpchp
    reiserfs              239616  2
    edd                    26760  0
    fan                    21896  0
    ⋯⋯

    找到了usbcore那一行吗?core就是核心,基本上你要在你的电脑里用USB设备,那么两个模块是必须的:一个是usbcore,这就是核心模块;另一个是主机控制器的驱动程序,比如这里usbcore那一行我们看到的ehci_hcd和uhci_hcd,你的USB设备要工作,合适的USB主机控制器模块也是必不可少的。

    usbcore负责实现一些核心的功能,为别的设备驱动程序提供服务,提供一个用于访问和控制USB硬件的接口,而不用去考虑系统当前存在哪种主机控制器。至于core、主机控制器和USB驱动三者之间的关系,如下图所示。

    USB驱动和主机控制器就像core的两个保镖,协议里也说了,主机控制器的驱动(HCD)必须位于USB软件的最下一层。HCD提供主机控制器硬件的抽象,隐藏硬件的细节,在主机控制器之下是物理的USB及所有与之连接的USB设备。而HCD只有一个客户,对一个人负责,就是usbcore。usbcore将用户的请求映射到相关的HCD,用户不能直接访问HCD。

    core为咱们完成了大部分的工作,因此咱们写USB驱动的时候,只能调用core的接口,core会将咱们的请求发送给相应的HCD。

    USB子系统与设备模型

    关于设备模型,最主要的问题就是,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上面登记,或者说挂牌。具体到USB子系统,每一个USB设备的驱动程序都会对应一个struct usb_driver结构,其中有一个struct device_driver driver成员,USB core为每一个设备驱动准备了一个函数,让它把自己的这个struct device_driver driver插入到usb_bus_type中的drivers链表中去。而这个函数正是我们此前看到的usb_register。而与之对应的usb_deregister所从事的正是与之相反的工作,把这个结构体从drivers链表中删除。

    而struct bus_type结构的match函数在USB子系统里就是usb_device_match函数,它充当了一个红娘的角色,在USB总线的USB设备和USB驱动之间牵线搭桥,类似于交大BBS上的鹊桥版,虽然它们上面的条件都琳琅满目的,但明显这里match的条件不是那么的苛刻,要更为实际些。

    可以说,USB core的确是用心良苦,为每一个USB设备驱动做足了功课,正因为如此,作为一个实际的USB设备驱动,它在初始化阶段所要做的事情就很少,很简单了,直接调用usb_register即可。事实上,没有人是理所当然应该为你做什么的,但USB core这么做了。所以每一个写USB设备驱动的人应该铭记,USB设备驱动绝不是一个人在工作,在他身后,是USB core所提供的默默无闻又不可或缺的支持。

  • 相关阅读:
    【HDOJ】1224 Free DIY Tour
    【HDOJ】1494 跑跑卡丁车
    【HDOJ】1495 非常可乐
    ACMer
    find the nth digit
    A C
    已知六条边的边长,求四面体体积
    快速排序
    {A} + {B}
    素数回文
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8448806.html
Copyright © 2020-2023  润新知