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()也返回了,要么