您的位置:首页 > 运维架构 > Linux

《Linux那些事儿之我是USB》我是U盘(9)总线、设备和驱动(下)

2011-07-11 12:26 274 查看
bus上的两张链表记录了每一个设备和驱动,那么设备和驱动这两者之间又是如何联系起来的呢?此刻,必须抛出这样一个问题,先有设备还是先有驱动?
在以前,先有的是设备,每一个要用的设备在计算机启动之前就已经插好了,插放在它应该在的位置上,然后计算机启动,然后操作系统开始初始化,总线开始扫描设备。每找到一个设备,就为其申请一个struct device结构,并且挂入总线中的devices链表中来,然后每一个驱动程序开始初始化,开始注册其struct device_driver结构,然后它去总线的devices链表中去寻找(遍历),去寻找每一个还没有绑定驱动的设备,即struct device中的struct device_driver指针仍为空的设备,然后它会去观察这种设备的特征,看是否是他所支持的设备,如果是,那么调用一个叫做device_bind_driver的函数,然后他们就结为了秦晋之好。换句话说,把struct device中的struct device_driver driver指向这个驱动,而struct device_driver driver把struct device加入它的struct list_head devices链表中来。就这样,bus、device和driver,这三者之间或者说它们中的两两之间,就给联系上了。知道其中之一,就能找到另外两个。一荣俱荣,一损俱损。
但现在情况变了,出现了一种新的名词“热插拔”。设备可以在计算机启动以后在插入或者拔出计算机了。因此,很难再说是先有设备还是先有驱动了。因为都有可能。设备可以在任何时刻出现,而驱动也可以在任何时刻被加载。所以,出现的情况就是,每当一个struct device诞生,它就会去bus的drivers链表中寻找自己的另一半;反之,每当一个一个structdevice_driver诞生,它就去bus的devices链表中寻找它的那些设备。如果找到了合适的,那么和之前那种情况一样,调用device_bind_driver绑定好。如果找不到,没有关系,等待吧。
事实上,完善这个三角关系,正是每一个设备驱动初始化阶段所完成的重要使命之一。让我们还是回到代码中来,usb_register函数调用是调用了,但是传递给他的参数是什么呢?
我们注意到,调用usb_register函数的代码如下:
1073 /* registerthe driver, return usb_register return code if error */
1074 retval = usb_register(&usb_storage_driver);
是的,传递了一个叫做usb_storage_driver的家伙,这是什么?同一个文件中:
1055 static struct usb_driver usb_storage_driver ={
1056 .name = "usb-storage",
1057 .probe = storage_probe,
1058 .disconnect= storage_disconnect,
1059 #ifdef CONFIG_PM
1060 .suspend = storage_suspend,
1061 .resume = storage_resume,
1062 #endif
1063 .pre_reset= storage_pre_reset,
1064 .post_reset = storage_post_reset,
1065 .id_table= storage_usb_ids,
1066 };
可以看到这中定义了一个struct usb_driver的结构体变量,usb_storage_driver,关于usb_driver我们上节已经说过了,当时主要说的是其中的成员driver,而眼下要讲的则是另外几个成员。首先,owner是用来给模块计数的,每个模块都这么用,赋值总是THIS_MODULE。而name就是这个模块的名字,USB Core会处理它,所以如果这个模块正常被加载了的话,使用lsmod命令能看到一个叫做usb-storage的模块名。CONFIG_PM是与电源管理相关的。下面重点要讲一讲,.probe和.disconnect以及这个id_table。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: