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 />

说明了为啥咱们要显式的去指定对齐方式.具体来说,unsigned long hostdata[0] __attribute__<br />

((aligned (size<strong>of</strong>(unsigned long))))就是表示hostdata[0]将以size<strong>of</strong>(unsigned long)字节对齐,显<br />

然不同的硬件平台size<strong>of</strong>(unsinged long)是不一样的.而之前咱们遇到过的那个定义于<br />

include/linux/usb_ch9.h 中的struct usb_device_descriptor 以及struct<br />

usb_interface_descriptor 结构体,则在最后跟了这么一句:__attribute__ ((packed)),这个表示使用<br />

最小可能的对齐,从packed 的字面意思也很清楚,紧凑一点,别瞎留空间,实际上这也就是给编译器的一个<br />

命令,告诉编译器,嘿,一会节省一点,别浪费空间啊.<br />

107<br />

好,介绍完<strong>Scsi</strong>_Host 数据结构,咱们继续回到那曾经的usb_stor_acquire_resources()函数中<br />

来,us->host 得到了她想要的,然后下面798 行,只是一句赋值,把us->host->hostdata[0]赋值为<br />

(unsigned long)us,这样做有什么用咱们后面遇到了再说.<br />

总之,scsi_host_alloc()这么一调用,就是给咱们的struct <strong>Scsi</strong>_Host 结构提申请了空间,真正要想<br />

模拟一个scsi 的情景,需要三个函数,scsi_host_alloc(),scsi_add_host(),scsi_scan_host().只有调用<br />

了第二个函数之后,scsi 核心层才知道有这么一个host 的存在,而只有第三个函数被调用了之后,真正的设<br />

备才被发现.这些函数的含义和它们的名字吻合的很好.不是吗?<br />

最后需要指出的是,scsi_host_alloc()需要两个参数,第一个参数是struct scsi_host_template 的<br />

指针,咱们当然给了它&usb_stor_host_template,而第二个参数实际上是被称为driver 自己的数据,咱<br />

们传递的是size<strong>of</strong>(us).这样子,scsi_host_alloc()中就会给咱们申请内存空间,即为us 申请内存空间.不<br />

过有趣的是,us 我们早就申请好了空间,这里多申请一份是否有必要呢?注意到struct <strong>Scsi</strong>_Host 里边不<br />

是<br />

有一个hostdata 么,理由是这样的,struct us_data 这个冬冬是我们在usb-storage 模块里边专门定义<br />

的,<br />

而一会我们和scsi 层打交道,我们要注册一些函数,提供给scsi 核心层,让核心层去调用,这些函数原型如何<br />

是scsi 层说了算的,scsi 层准备了一些函数指针,我们只是把这些指针赋好值,scsi 层就知道在什么时候该<br />

调<br />

用哪个函数了.所以既然原型是人家提供的,那么人家肯定不知道我们会有一个struct us_data 这么一个<br />

结<br />

构体,所以我们在定义函数的时候就不能把struct us_data 当作一个参数,但是我们专门为自己这个模块<br />

准<br />

备的结构体又不可能不用,那怎么办?好办,scsi 核心层是认struct <strong>Scsi</strong>_Host 这个结构体的,而这个结构<br />

体<br />

在设计的时候就专门准备了一个unsigned long hostdata[0]来给别的设备驱动使用.那我们还客气什么,<br />

让这个指针指向我们的us 就可以了.以后要用us 再通过hostdata[0]来获得就是了.所以刚才我们看到了<br />

us->host->hostdata[0]被赋值为(unsigned long)us.这个host 就是我们之后会一直用到的struct<br />

<strong>Scsi</strong>_Host 结构体,hostdata[0]是一个unsigned long 的变量,us 是一个指针,所以这就使得这个变量<br />

的<br />

值等于这个指针指向的地址.而之后我们会经常看见scsiglue.c 中的函数里边使用如下的赋值语句:<br />

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

所以意思就很明确了.指针被定义为原来us 所指向的那个地址.所以看似又定义了一个struct<br />

us_data *us,实际上只不过是原来是一个全局变量,现在是一个局部变量而已.至于在scsi_host_alloc()<br />

中又申请了一段大小为size<strong>of</strong>(us)的内存,既然已经有内存了就没有必要用它了,只是借用hostdata 这个<br />

指针而已.当然,这样做不太合理,浪费内存,与我党长期以来坚持的艰苦朴素的作风是相违背的,在我党如今<br />

强调以艰苦奋斗为荣,以骄奢淫逸为耻的背景下,这段代码自然遭到了广大人民群众的质疑,因此毫无疑问,

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

Saved successfully!

Ooh no, something went wrong!