07.06.2013 Views

Scsi - Index of

Scsi - Index of

Scsi - Index of

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

wait_for_completion()这样当前进程就会进入睡眠,处于一种等待状态,而另一个进程可能会去做某事,<br />

当它做完了某件事情之后,它会调用complete()函数,一旦它调用这个complete 函数,那么刚才睡眠的这<br />

个进程就会被唤醒.这样就实现了一种同步机制,或者叫等待机制.那么我们来看complete 函数在哪里被<br />

调<br />

用的,换句话说,咱们这里一旦睡去,何时才能醒来.<br />

84<br />

还记得在调用usb_fill_control_urb()填充urb 的时候咱们设置了一个urb->complete 指针吗?没错,<br />

当时咱们就看到了,urb->complete=usb_stor_blocking_completion,这相当于向usb host<br />

controller driver 传达了一个信息.所以,当urb 传输完成了之后,usb host controller 会唤醒她,但不会<br />

直<br />

接唤醒她,而是通过执行之前设定的urb 的complete 函数指针所指向的函数,即调用<br />

usb_stor_blocking_completion()函数去真正唤醒她.usb_stor_blocking_completion()函数定义于<br />

drivers/usb/storage/transport.c 中:<br />

109 /* This is the completion handler which will wake us up when an URB<br />

110 * completes.<br />

111 */<br />

112 static void usb_stor_blocking_completion(struct urb *urb, struct pt_regs *regs)<br />

113 {<br />

114 struct completion *urb_done_ptr = (struct completion *)urb->context;<br />

115<br />

116 complete(urb_done_ptr);<br />

117 }<br />

这个函数就两句话,但她调用了complete()函数,urb_done_ptr 就被赋为urb->context,而<br />

urb->context 是什么? usb_stor_msg_common()函数中,152 行,可不就是把刚初始化好的<br />

urb_done赋给了它么?这个函数可是Linux内核的核心函数,不要问她从哪里来,她会告诉你她来自内核底<br />

层,没错,她的户口在kernel/sched.c,很显然,她就是唤醒刚才睡眠的那个进程.换言之,到<br />

这,wait_for_completion()将醒来,从而继续往下走.<br />

如果你足够好奇,你会问如果超时,那么timeout_handler 会被调用,于是usb_unlink_urb 会被调用,<br />

然后呢?其实usb_stor_blocking_completion 还是会被调用,而且会设置urb->status 以告诉大家这<br />

个<br />

urb 被cancel 了.<br />

下面只剩下几行代码了.首先是clear_bit()清除US_FLIDX_URB_ACTIVE,表明这个urb 不再是<br />

active 了.因为该干的事都干完了,就好比您的包裹已经寄到了,那显然您填的那个单子就没有用了.至少她<br />

上面应该有标志表明这份单子对应的包裹已经送过了,不要再送了.如果是超时了,那么也是一样的,urb 都<br />

被cancel 了,当然就不用设为active 了.<br />

然后下一行,如果这时timeout 还大于0,那么说明刚才您设的那个超时闹钟还没到过期,而您该做的事<br />

情却已经做完了,所以这个闹钟就不需要设了,就好比邮局承诺您三天寄到,完了您记住了,三天她要没寄到,<br />

您就去索赔,所以您自个儿就订了个闹钟,三天真到期了您就可以去索赔,但是如果人家两天就给您寄到了,<br />

那您这个闹钟就没意义了嘛不是,所以这样您就得取消这个闹钟,省得她那弦老紧绷着,这里您也得删除刚才<br />

那个to_timer,这样您可以调用Linux 内核为您提供的函数del_timer_sync(),她的参数就是刚才这个<br />

to_timer 的地址.最后一句,usb_stor_msg_common()函数终于该返回了,return<br />

us->current_urb->status,返回的就是urb 的status.于是我们总算是可以离开这个函数了.<br />

返回之后,又回到usb_stor_control_msg()中来,如果status 是0,那么说明成功传输了,对于成功传输<br />

的情况,urb 的actual_length 将被赋值为实际传输长度,然后usb_stor_control_msg()也返回了,要么

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!