快速业务通道

u盘驱动学习(四)代码结构之主框架

作者 佚名技术 来源 Linux系统 浏览 发布时间 2012-04-10
linux内核采用的是模块机制,可以通过 module_init(&usb_stor_init)将U盘驱动程序注册到内核中,在usb_stor_init()中,向 usb_register()函数传递了一个usb_driver的结构体usb_storage_driver代表一个具体的驱动程序. usb_storage_driver初始化的时候,其成员指向了驱动程序代码中的特定结构体或函数,其中最重要的是 “probe=storage_probe”,系统会将U盘设备的id和interface作为参数传给这个函数,函数会通过id去搜索此驱动程序支持的 设备表,判断此U盘是否是设备表的一员,并通过此id获得此设备的生产厂商等信息. storage_probe()函数还有一个重要的部分就是对us_data 变量 us 的初始化,包括主要的四个部分:1、把参数 interface 中的信息存到 us 里;2、跟据id把设备的硬件信息存到 us 里;3、把设备支持的传输协议(在这里是bulk-only)及支持的命令集(在这里是scsi)存到 us 里.4、为控制端点及输入输出端点构造管道.上述初始化完成之后,程序便进入了 usb_stor_acquire_resources(us) 函数中了. 驱动程序要实现设备和主机的通信,使用一个叫urb的结构体,程序将urb提交给底层的 usb core,usb core 接到 urb后会找到相应的 host controller 去实现具体数据的传输.因此在 usb_stor_acquire_resources(us) 的一开始,变为 us 的成员 current_urb 申请了内存空间,并在调用 p = usb_stor_Bulk_max_lun(us) 中对其进行了初始化. usb_stor_Bulk_max_lun(us) 展示了一个完整的控制过程,它的功能是获取设备的max lun,对U盘来说这个值永远是0(读卡器可能不为0).此函数对 urb 的部分成员进行了赋值,并构造了一个合法的控制命令包,将其填充到了urb中,然后调用 usb_submit_urb(urb,timeout) 想内核提交 urb,如果 urb提交成功,程序会进入睡眠状态,等命令或数据传输完成后被唤醒.在得到设备的 max lun 后就返回了 usb_stor_acquire_resources() 中并运行 us->host = scsi_host_alloc(&usb_stor_host_template,sizeof(us)). 作为一种存储设备,U盘遵循的是SCSI命令集,U盘连到主机上后会被虚拟成scsi 设备.在函数scsi_host_alloc()就是为U盘申请一个scsi host的数据结构,并向scsi核心层进行注册,命令来了的时候,这个scsi host能把命令传递给设备.虚拟scsi卡申请完成之后,函数返回,程序继续运行,进入了P = kernel_thread(usb_stor_control_thread,us,CLONE_VM)当中.这个函数创建了一个子进程,此进程执行 usb_stor_control_thread()函数,us是传递给它的参数.从这里开始,驱动程序一分为二. 父进程创建完子进程后,变进入睡眠状态,后被子进程唤醒,返回到usb_stor_acquire_resources() 中,继续返回到最初的函数 storage_probe()函数中,进行 scsi 的注册,并在创建完精灵进程 usb_stor_scan_thread() 之后执行完毕.至此父进程结束,下面主要看一下作为守护进程的子进程. 在子进程中,函数 usb_stor_control_thread(us) 的主体是一个死循环,在刚进入死循环时程序会进行睡眠,直到一个 scsi 命令被传递进来. scsi命令由结构体 srb构成,因此 us 中的成员变量 srb 也会指向此命令. 子进程被唤醒后,会读取 us 里面 srb的值,判断数据的传输方向及其他的一些特征是否合法.如果一切都顺利的话,就会执行 proto_handler(us-srb,us) 函数,进行真正的bulk传输. proto_handler()是一个函数指针,在前面的get_protocol(us) 函数中被赋值为 usb_stor_transparent_scsi_command(srb,us) ,在这个函数中,最重要的是其调用的另一个函数 usb_stor_invoke_transport(srb,us).这才是bulk传输真正进行的地方. 上面我们提到了子进程死循环中bulk传输真正进行的地方,usb_stor_invoke_transport(srb,us),下面我们就看一下这个函数结构. 程序一开始构造了一个CBW,然后通过 us的 transport 指针调用了 usb_stor_Bulk_transport(srb,us) 函数,这个函数又调用 usb_stor_bulk_transfer_buf(5) 函数填充了一个bulk urb,后者又通过 usb_stor_msg_common() 提交给了usb core (此处与前面获得 max lun 的过程大致相似),告诉设备要进行数据传输.如果命令传输成功,则返回 usb_stor_Bulk_transport(srb,us) 程序中执行 usb_stor_bulk_transfer_sg()开始真正的数据传输.数据传输完成后,再一次调用 usb_stor_bulk_transfer_buf()来获得CSW.这样就完成了bulk传输的三个阶段:命令传输,数据传输,状态传输.

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号