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