Linux 那些事儿之我是U 盘 ---------------------------------------------------------------------------------------------------------------------- 摘要 2005 年6 月,复旦大学微电子系本科毕业答辩上,老师问我:请你用一句话介绍一下usb 技 术.我回了一句:老师,你有病吧,要能用一句话介绍我还费这么大劲写这么长的文章干嘛? 关键词:Linux, Kernel, 2.6, bus, usb, device driver, mass storage, scsi, urb, bulk, control, host, pipe, command, 林志玲 --------------------------------------------------------------------------------------------------------------------
引子 也许是在复旦养成了昼伏夜出的坏习惯,工作之后也总是很晚也不愿意睡.来到北京之后,开 始听广播听都市之声的北京不眠夜.这个节目是从23 点直到第二天凌晨一点,我常常是听完 了才会睡觉.无论是北京还是上海,对我来说,生存总是那么困难,生活的压力总是那么大,每 天只有在这个节目中才能够寻找到一丝温暖.我不喜欢躺在床上听,而是喜欢一边听一边做 点别的事情,于是心血来潮的决定,写点文字吧,听着电波里别人分享心情,不妨也用文字来记 录自己的心情吧. 我首先想到的是写一些和Linux 相关的文字.事实上我并不喜欢Linux,学习Linux 完全是 一 种无奈,工作中要用,迫于生计,不得不去学习,而学习Linux 的过程中唯一让我觉得还有些 乐 趣的是当遇到问题的时候可以去网上问去网上查,很多人写了很多文档可以让我们这些菜鸟 们参考学习,这样才让我们在工作中走了很多弯路.挺感谢那些分享自己知识的人.碰巧最近 3 我也看了点冬冬,并且这些冬冬在网上的资料也比较少,所以我想我不妨也把自己那一夜的 收获写出来,或许以后也能给别人提供一些帮助,想想也是,整个Linux 社区不正是这样吗, 像 陈奕迅唱的那样,”把一个人的温暖转移到另一个人的胸膛”. 我要写的是Linux 设备驱动程序相关的,主要分析的是Linux 中与U 盘相关的那部分代码. 过去也没有看过,但是今年4 月底的某一天,一个偶然的原因,我一时冲动就看了一遍.我们 几 个同学在人大附近打麻将,打到夜深了,因为我们几人人住的位置都离得挺远的,各自回去都 得打车,于是决定不如去权金城开个房间,晚上就睡那得了.在权金城洗浴中心,和几个同学洗 浴过后,有人去按摩了,而我和另一个人则留在了房间里,无聊中,那位哥们见我带了电脑,说 他有部A 片,很不错,不是很大,所以他存在U 盘里的,他还挺逗的说这是2008 年北京奥运 会 指定A 片,问我有没有兴趣,这还用问,当然有兴趣了,于是立马打开电脑,插入u 盘,然后不一 会我就傻了,因为我的电脑根本就不能识别U盘,首先我的电脑比较旧,装的是双系统,一个是 Win 98,这个没办法,没有U 盘驱动,另一个是Linux,2.6 的内核,按理应该是支持U 盘的, 问题是实际情况却是我没有看到U 盘,/dev/目录下面根本没有这么一个盘符,于是我没办 法 了,一脸沮丧,而同学在旁边自然表示出了对Linux 很鄙视的神情. 过了一会,他去看电视了,正好有英超,我却没有心情看电视,想想就觉得奇怪,怎么会不能使 用U 盘呢,这不可能啊,一定是我自己对Linux 下面的一些冬冬没有弄清楚,于是我决定好好 看看问题到底出在哪,记得当时看了一下/var/log/messages 这个日志文件里边好像记录 了一些信息,感觉像是一些错误信息,但是看不明白它到底在说什么.同学开始劝我,算了算 了, 改天再看吧,这话我可不愿意听,不是说Linux 内核源代码是公开的吗,大不了看看源代码, 搞 清楚工作原理了还怕问题不能解决?无非就是一些C 代码而已,好歹哥们也是认真学过谭浩 强大哥那本C 程序设计的.而且当初那本书课后习题老师基本上都让我们做了,虽说是参考 了那本习题解答的书,可就算写代码不行,读代码还是没问题吧,语法什么的基本上还是很清
- Page 1 and 2: 摘要 ............................
- Page 3: 迷雾重重的Bulk 传输(二)....
- Page 7 and 8: usb.h datafab.h dpcm.h initializers
- Page 9 and 10: 的Linux 内核划分为许许多
- Page 11 and 12: 目录下执行make 了.Ok,make 之
- Page 13 and 14: 只 是一个usb 接口.这些口
- Page 15 and 16: 中也定义了这么一些数据
- Page 17 and 18: 511 * @driver: the driver model cor
- Page 19 and 20: 233 .owner = THIS_MODULE, 234 .name
- Page 21 and 22: 91 * construct these entries. Each
- Page 23 and 24: 324 struct usb_host_config *actconf
- Page 25 and 26: 22 88 * @class_dev: driver model's
- Page 27 and 28: 必须给各个地方取名,完了
- Page 29 and 30: 26 136 trans_cmnd transport; /* tra
- Page 31 and 32: 944 init_MUTEX_LOCKED(&(us->sema));
- Page 33 and 34: 147 #if !defined(CONFIG_BLK_DEV_UB)
- Page 35 and 36: 124 #define USB_DEVICE_ID_MATCH_DEV
- Page 37 and 38: intf 来代替. us 之所以重要,
- Page 39 and 40: 睡眠,那就得用GPF_ATOMIC,这
- Page 41 and 42: 504 if (msg >= 0 && !(unusual_dev->
- Page 43 and 44: 179 } 180 181 static struct us_unus
- Page 45 and 46: 711 /* Submitted by Hartmut Wahl */
- Page 47 and 48: 3. useProtocol 为US_SC_DEVICE, use
- Page 49 and 50: Bus 004 Device 001: ID 0000:0000 Bu
- Page 51 and 52: 993 result = get_pipes(us); 994 if
- Page 53 and 54: 631 us->transport_reset = usb_stor_
- Page 55 and 56:
659 us->max_lun = 0; 660 break; 661
- Page 57 and 58:
740 /* Calculate and store the pipe
- Page 59 and 60:
storage 会有两个bulk 端点,用
- Page 61 and 62:
比如说,复旦大学,有一个主
- Page 63 and 64:
1079 #define PIPE_ISOCHRONOUS 0 108
- Page 65 and 66:
782 us->unusual_dev->initFunction(u
- Page 67 and 68:
630 * each frame is in the fields o
- Page 69 and 70:
716 * Bulk URBs may 717 * use the U
- Page 71 and 72:
802 int number_of_packets; /* (in)
- Page 73 and 74:
先说互斥锁.它诞生于这样
- Page 75 and 76:
920 US_DEBUGP("GetMaxLUN command re
- Page 77 and 78:
148 /* set up data structures for t
- Page 79 and 80:
90 * @wValue: matches the USB wValu
- Page 81 and 82:
830 void *transfer_buffer, 831 int
- Page 83 and 84:
25 { 26 x->done = 0; 27 init_waitqu
- Page 85 and 86:
都会过期,我开始怀疑,在这
- Page 87 and 88:
是实际长度,要么就是不成
- Page 89 and 90:
87 258 行,usb_pipeendpoint,定义
- Page 91 and 92:
对爱你的人掘了一条无法
- Page 93 and 94:
Type: Direct-Access ANSI SCSI revis
- Page 95 and 96:
416 /* 417 * this defines our host
- Page 97 and 98:
69 * Ioctl interface 70 * 71 * Stat
- Page 99 and 100:
155 * "is this a new device" checks
- Page 101 and 102:
241 char *proc_name; 242 243 /* 244
- Page 103 and 104:
328 * True if the low-level driver
- Page 105 and 106:
可以看到这个函数的参数
- Page 107 and 108:
451 short unsigned int max_sectors;
- Page 109 and 110:
地 说明了为啥咱们要显式
- Page 111 and 112:
usb_stor_acquire_resources()函数
- Page 113 and 114:
341 } 342 343 /* reject if target !
- Page 115 and 116:
内核的核心位置,kernel/exit.c
- Page 117 and 118:
1023 dissociate_dev(us); 1024 retur
- Page 119 and 120:
917 行,再次判断设备有没有
- Page 121 and 122:
181 182 /* fail the command if we a
- Page 123 and 124:
83 struct timer_list eh_timeout; /*
- Page 125 and 126:
123 两个scsi_done,一个是struct
- Page 127 and 128:
56 jiffie count on our counter, the
- Page 129 and 130:
中 看到如下的定义: UNUSUAL_
- Page 131 and 132:
269 memcpy(data+16, us->unusual_dev
- Page 133 and 134:
一切准备好了之后,我们就
- Page 135 and 136:
238 (sg->offset + *offset) & (PAGE_
- Page 137 and 138:
所以对于那些不能相应INQUI
- Page 139 and 140:
239 行对unsigned int sglen 赋值
- Page 141 and 142:
请求,所以这里就判断abort
- Page 143 and 144:
112 case GPCMD_READ_HEADER: what =
- Page 145 and 146:
到北京,每每只有在夜深人
- Page 147 and 148:
580 /* 581 * If we have a failure,
- Page 149 and 150:
666 memcpy(srb->cmnd, old_cmnd, MAX
- Page 151 and 152:
950 struct bulk_cb_wrap *bcb = (str
- Page 153 and 154:
1034 /* get the status again */ 103
- Page 155 and 156:
426 /* store the actual length of t
- Page 157 and 158:
后她会给host 返回一个CSW.CB
- Page 159 and 160:
296 } 297 298 US_DEBUGP("-- transfe
- Page 161 and 162:
491 * scatter-gather or not, and ac
- Page 163 and 164:
迷雾重重的 Bulk 传输(五) us
- Page 165 and 166:
然后把她赋给了result.而us->
- Page 167 and 168:
而bcs->Status,标志命令执行
- Page 169 and 170:
就必须设置US_FL_IGNORE_RESIDUE
- Page 171 and 172:
485 }; 486 这是一个字符数组
- Page 173 and 174:
srb->sense_buffer 里边的东西.S
- Page 175 and 176:
一个类似的函数,名叫usb_sto
- Page 177 and 178:
这种命令应该由mid level 来
- Page 179 and 180:
Disk /dev/sda: 146.1 GB, 1461631057
- Page 181 and 182:
through to the most significant bit
- Page 183 and 184:
1192 USB_TYPE_CLASS | USB_RECIP_INT
- Page 185 and 186:
315 行,scsi_report_device_reset(),
- Page 187 and 188:
285 US_DEBUGP("No reset during disc
- Page 189 and 190:
229 /* Wait for the aborted command
- Page 191 and 192:
两个函数中需要判断它,一
- Page 193 and 194:
associate_dev()相对应.我们来
- Page 195 and 196:
束for 死循环,从而usb_stor_con
- Page 197 and 198:
317 for (i = 1; i < us->host->max_i