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.

storage 协议,还需遵守transparent scsi 规范.从驱动程序的角度来看,它和一般的scsi 磁盘差不多.正<br />

是<br />

因为如此,所以U 盘的工作真正需要的是四个模块,usbcore,scsi_mod,sd_mod,以及咱们这里的<br />

usb-storage,其中sd_mod 恰恰就是scsi disk 的驱动程序.没有它,你的scsi 硬盘就别想在Linux 下面<br />

转起来.看看它的代码,你就可以去电脑报投稿,发一篇”玩转Linux 下的scsi 硬盘”这样的文章.<br />

那么我们从哪里开始去接触这些scsi 命令呢?别忘了我们现在的主题,内核守护进程,别忘了我们曾经有<br />

一段代码只讲到一半就没讲了.没错,那就是usb_stor_control_thread(),当初我们用kernel_thread 创<br />

建它的时候就说了,从此以后一个进程变成两个进程,而我们刚才沿着storage_probe 讲完的是父进程,父<br />

进程最终返回了,而子进程则没有那么简单,我们已经说过,usb_stor_control_thread()中的死循环注定<br />

了这个子进程是一个永恒的进程,只要这个模块还没有被卸载,或者说还没有被要求卸载,这个子进程就必将<br />

永垂不朽的战斗下去.于是让我们推开记忆的门,回过来看这个函数,当初我们讲到了303 行,由于<br />

us->sema 一开始就是锁着的,所以down_interruptible 这里一开始就进入睡眠了,只有在接到唤醒的<br />

信<br />

号或者锁被释放了释放锁的进程来唤醒它它才会醒过来.那么谁来释放这把锁呢?<br />

有两个地方,一个是这个模块要卸载了,这个我们稍后来看.另一个就是有scsi 命令发过来了.scsi 命令从<br />

哪里发过来?很简单,scsi 核心层,硬件上来说,scsi 命令就是scsi 主机到scsi 设备,而从代码的角度来<br />

说,scsi 核心层要求为每一个scsi host 实现一个queuecommand 命令,每一次应用层发送来了scsi 命<br />

令<br />

了,比如你去读写/dev/sda,最终scsi 核心层就会调用与该host 相对应queuecommand,(确切地说是<br />

struct <strong>Scsi</strong>_Host 结构体中的成员struct scsi_host_template 中的成员指针queuecommand,这是<br />

一<br />

个函数指针.)那么我们来看,当初我们定义的struct scsi_host_template usb_stor_host_template,<br />

其中的确有一个queuecommand,我们赋给它的值也是queuecommand,即我们让queuecommand<br />

指向一个叫做queuecommand 的函数,在struct scsi_host_template 的定义中,函数指针的原型为:<br />

107 int (* queuecommand)(struct scsi_cmnd *,<br />

108 void (*done)(struct scsi_cmnd *));<br />

而我们所定义的queuecommand()函数又在哪里呢?在drivers/usb/storage/scsiglue.c 中:<br />

165 /* queue a command */<br />

166 /* This is always called with scsi_lock(srb->host) held */<br />

167 static int queuecommand(struct scsi_cmnd *srb,<br />

168 void (*done)(struct scsi_cmnd *))<br />

169 {<br />

170 struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];<br />

171<br />

172 US_DEBUGP("%s called\n", __FUNCTION__);<br />

173 srb->host_scribble = (unsigned char *)us;<br />

174<br />

175 /* check for state-transition errors */<br />

176 if (us->srb != NULL) {<br />

177 printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",<br />

178 __FUNCTION__, us->srb);<br />

179 return SCSI_MLQUEUE_HOST_BUSY;<br />

119<br />

180 }

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

Saved successfully!

Ooh no, something went wrong!