Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
具体到usb storage,我们不管信号量和锁在Linux 中是怎么实现的,它们之间是否有区别对我们来说也<br />
无所谓,事实上,usb-storage 中使用的都是锁,即便是信号量,也是把它当成锁来使用,可曾记得我们当初<br />
把<br />
信号量的初始化为1 了?当信号量初始化为1,那么对我们来说,它就相当于退化为一把锁了.而锁,只有两种<br />
状态,上锁和解锁.<br />
此前我们见过很多次两组函数,但我们一直绝口不提.<br />
她们就是scsi_lock()和scsi_unlock(),以及down(&us->dev_semaphore)和<br />
up(&us->dev_semaphore).<br />
先来看第一组.她们是我们自己定义的宏.来自drivers/usb/storage/usb.h.<br />
174 /* The scsi_lock() and scsi_unlock() macros protect the sm_state and the<br />
175 * single queue element srb for write access */<br />
176 #define scsi_unlock(host) spin_unlock_irq(host->host_lock)<br />
177 #define scsi_lock(host) spin_lock_irq(host->host_lock)<br />
显然,这两个函数就像牛郎织女一样,是一对.而她们的作用,就是利用自旋锁来保护资源,这把锁就是<br />
struct <strong>Scsi</strong>_Host 的一个成员spinlock_t *host_lock.那么在什么情况下需要使用这两个自旋锁函数来<br />
保护资源呢?<br />
当你要写us->srb 的时候,(不是写us->srb 的元素,而是写us->srb,比如令us->srb=NULL),这种时<br />
候,你需要使用这把自旋锁.另一种情况是,当你调用scsi mid layer(scsi 中层)的函数时,有时候这些函数<br />
要求调用者拥有这把锁,即host_lock.<br />
搜索一下,发现一共有7 处使用了scsi_lock.<br />
我们列举一些来.<br />
第一处,drivers/usb/storage/usb.c:usb_stor_release_resources()函数中,<br />
839 scsi_lock(us->host);<br />
840 us->srb = NULL;<br />
841 scsi_unlock(us->host);<br />
199<br />
这个不用解释了吧,赤裸裸的写us->srb,自然要用scsi_lock/scsi_unlock.<br />
第二处,drivers/usb/storage/transport.c:usb_stor_reset_common()函数中,<br />
1121 scsi_lock(us->host);<br />
1122 usb_stor_report_device_reset(us);<br />
1123 set_bit(US_FLIDX_RESETTING, &us->flags);<br />
1124 clear_bit(US_FLIDX_ABORTING, &us->flags);<br />
1125 scsi_unlock(us->host);<br />
这就是第二种情况,因为这里调用了usb_stor_report_device_reset(),这个函数来自<br />
drivers/usb/storage/scsiglue.c,也是我们定义的,<br />
308 /* Report a driver-initiated device reset to the SCSI layer.<br />
309 * Calling this for a SCSI-initiated reset is unnecessary but harmless.<br />
310 * The caller must own the SCSI host lock. */<br />
311 void usb_stor_report_device_reset(struct us_data *us)<br />
312 {<br />
313 int i;<br />
314<br />
315 scsi_report_device_reset(us->host, 0, 0);<br />
316 if (us->flags & US_FL_SCM_MULT_TARG) {