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.

都会过期,我开始怀疑,在这个世界上,还有什么东西是不会过期的?<br />

有时候我也被这个问题所困扰,我不知道是我不明白还是这世界变化太快.连Linux 中都引入了过期这么<br />

一个概念.说文雅一点就是超时.设置一个时间,如果时间到了该做的事情还没有做完,那么某些事情就会发<br />

生.<br />

83<br />

比如,咱们需要做这样一些事情,定个闹钟,比如咱们需要烤蛋糕,现在是8点30,而咱们要烤45分钟,所以<br />

咱们希望闹钟9 点一刻响,然后当时间到了,闹钟就如咱们期待的一样,响个不停.在计算机中,咱们也需要做<br />

这样的事情,有些事情,咱们需要时间控制,特别是网络,通信,等等,凡是涉及数据传输的事儿,就得考虑超时,<br />

换句话说,定个闹钟,你要是在这个给定的时间里还没做好你该做的事情,那么停下来,别做了,肯定有问题,<br />

比如,咱们如果烤蛋糕45 分钟,发现蛋糕一点香味都没有,颜色也没变,那肯定有问题,别烤了,先检查一下烤<br />

箱是不是坏了,是不是停电了,等等.而具体到咱们这里,需要用一个闹钟,或者叫专业一点,定时器,如果时间<br />

到了,就执行某个函数,这个功能Linux 内核的时间机制已经实现了,咱们只需要按"说明书"调用相应的接<br />

口<br />

函数即可.看代码,190 行,如果timeout>0,也就是说需要设置闹钟,那么首先需要定义一个struct<br />

timer_list 结构体的变量,咱们这里定义的变量叫做to_timer(在usb_stor_msg_common 一开始就定<br />

义了的),然后用init_timer()函数和add_timer()函数来真正实现设置闹钟,init_timer()是初始化,然后<br />

设置好之后调用add_timer 才能让闹钟生效.具体怎么设置的呢?在add_timer()之前,为<br />

to_timer.expires 赋值为jiffies+timeout,to_timer.function 赋值为<br />

timeout_handler,to_timer.data 赋值为us.这表示,超时时间点为当前时间加上一个<br />

timeout,(jiffies,Linux 内核中赫赫有名的全局变量,表示当前时间),timeout 咱们前面调用<br />

usb_stor_msg_common 的时候给设置成了HZ,也就是1 秒.当时间到了之后,timeout_handler 函数<br />

会被执行,而us 作为参数传递给她.不妨来看一下timeout_handler 函数吧,她定义于<br />

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

119 /* This is the timeout handler which will cancel an URB when its timeout<br />

120 * expires.<br />

121 */<br />

122 static void timeout_handler(unsigned long us_)<br />

123 {<br />

124 struct us_data *us = (struct us_data *) us_;<br />

125<br />

126 if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {<br />

127 US_DEBUGP("Timeout -- cancelling URB\n");<br />

128 usb_unlink_urb(us->current_urb);<br />

129 }<br />

130 }<br />

看得出,其实也没做什么,就是清除US_FLIDX_URB_ACTIVE flag,然后调用usb_unlink_urb()函数<br />

撤销当前这个urb.还记得刚才说的那个同步异步了吗?这正是刚才说的那个异步的情形,显然此刻这个函数<br />

不能睡眠,否则整个driver 就挂了...<br />

紧接着,199 行,非常重要的一句wait_for_completion(&urb_done),这句话会使本进程进入睡眠.别<br />

忘了刚才我们那句init_completion(&urb_done),urb_done 是一个struct completion 结构体变量,<br />

这个定义在usb_stor_msg_common()函数的第一行就出现了.显然completion 是Linux 中同步机制<br />

的一个很重要的结构体.与wait_for_completion 对应的一个函数是complete().其用法和作用是这样<br />

的:<br />

首先我们要用init_completion 初始化一个struct completion 的结构体变量,然后调用

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

Saved successfully!

Ooh no, something went wrong!