You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
123<br />
两个scsi_done,一个是struct scsi_cmnd *srb 的成员指针,一个是scsi 核心层的函数名.虽然它们同名,<br />
但是是两个不同的冬冬,就好像满世界都是叫张伟,王伟,李伟,刘伟的一样,名字相同人不同,很正常.<br />
最后,192 行,令us->srb 等于这个srb.而193 行,这正是我们苦苦寻找的代码,正是这个<br />
up(&us->sema),唤醒了我们的守护进程.之后,195 行,这个函数本身就结束了,像烟花熄灭,像夜空沉寂.<br />
而我们显然就该去看那个usb_stor_control_thread()了.因为,她醒了,她终于醒了.<br />
彼岸花的传说(五)<br />
燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候;老婆离了,有再找的时候,孩子<br />
跑了,有回来的时候;煮熟的鸭子飞了,有飞回来的时候.一个函数没讲完就跳走了,有再回来的时候.其实,那<br />
些人,那些事,终究不曾远离.<br />
于是,她再一次进入我们的视野.<br />
她就是usb_stor_control_thread().唤醒她的是来自queuecommand 的up(&(us->sema)),<br />
us->srb 被赋值为srb,而srb 是来自scsi 核心层在调用queuecommand 时候传递进来的参数.聚焦<br />
usb_stor_control_thread(),309 行, 前面说过,关于dev_semaphore 这把锁我们必须在看完整个模<br />
块之后再来总较高的角度来看,所以这里自然先跳过.<br />
312 行,没啥好说的,如果传进来的是NULL,那么还是退出吧.别无选择.(为什么命令是空就说明要结束了?<br />
因为如果srb 是空,那么scsi core 是不会调用queuecommand 的,道理不用说了吧,scsi core 也不傻,<br />
都没有命令它还调用底层的函数干嘛,吃错药了?那么queuecommand 没有调用的话是谁唤醒了这个守<br />
护进程?我们前面说了,唤醒它的有两个地方,一个是queuecommand,另一个就是模块要卸载了,准确的说<br />
是usb_stor_release_resources()函数,日后等我们遇到了这个函数再看吧,总之就是说当这个模块都要<br />
释放资源了,这时候srb 肯定会被设为NULL,然后这种情况下唤醒了我们这个守护进程,于是才有了这里这<br />
个判断语句.)<br />
318 行,host 也是一把锁,这把锁我们也到最后再来看.暂且不表.<br />
321 行至331 行,又是判断两个flag 有没有被设置,第二个不用多说了,看都看腻了,老是判断设备有没有<br />
被拔出,要是你的U 盘插进去了永远不拔出来,那么你可以把这个flag 相关的代码都删了,当然事实上是你<br />
不可能不拔出来,热插拔本来就是usb 设备的一大特性.所以你就能理解写代码的哥们儿为什么这么煞费苦<br />
心的去判断设备是不是已经不在了.那么第一个flag 呢,US_FLDX_TIMED_OUT,这个flag 的含义也如其<br />
字面意义一样,超时了,超时的概念在计算机的世界里比比皆是.不过对于这个flag,设置它的函数是<br />
command_abort,这个函数也是咱们提供的,由scsi 核心层去调用,由它那边负责计时,到了超时的时间它<br />
就调用command_abort.我们稍候会看,先不急.<br />
338 行,判断srb 的一个成员sc_data_direction, 先看DMA_BIDIRECTIONAL 这个宏.这个宏定义于<br />
include/linux/dma-mapping.h 中,<br />
7 /* These definitions mirror those in pci.h, so they can be used<br />
8 * interchangeably with their PCI_ counterparts */<br />
9 enum dma_data_direction {<br />
124<br />
10 DMA_BIDIRECTIONAL = 0,<br />
11 DMA_TO_DEVICE = 1,<br />
12 DMA_FROM_DEVICE = 2,<br />
13 DMA_NONE = 3,<br />
14 };<br />
在scsi_cmnd 结构体里边,有这么两个成员,