Scsi - Index of
Scsi - Index of Scsi - Index of
922 complete_and_exit(&us->scsi_scan_done, 0); 923 } 显而易见,这里的daemonize()又会让咱们再ps -el 的命令输出中看到有usb-stor-scan 这么一个精 灵进程. 116 903 行,delay_use 哪来的?同一文件中,最开始的地方,定义了一个静态变量, 101 static unsigned int delay_use = 5; 102 module_param(delay_use, uint, S_IRUGO | S_IWUSR); 103 MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); 设置了delay_use 为5,而module_param 是LK 2.6 提供的一个宏,使得delay_use 可以在模块被 装载的时候设定.(如果不设,那么她自然就是这里的值5,表示使用一个新的设备之前等待5 秒延时.)为啥要 delay 啊?不为啥,只是因为天上的星星会流泪,地上的玫瑰会枯萎.您插进去的u 盘也可能立刻又被您拔出 来了,试想您插入以后一两秒之内又拔出来,那么咱们下面也不用耽误工夫再检测了嘛不是. 903 行,判断delay_use>0,然后907 行,wait_event_interruptible_timeout(),它的第一个参数是 us->scsi_scan_wait,请回答,us->scsi_scan_wait 是第一次露面吗? 混迹外企这么多日子, 我可以很负责任的很有诚意的用英语语重心长的告诉你: The answer is no. 在 storage_probe()函数的最初,在us 的初始化时,scsi_scan_wait 被初始化了.947 行,init_waitqueue_head(&us->scsi_scan_wait),而在定义struct us_data 时,有一个成员就是 scsi_scan_wait,即wait_queue_head_t scsi_scan_wait,这些都是什么意思呢? 实际上wait_event_interruptible_timeout()是一个宏,它代表着Linux 中的一种等待机制,等待某个 事件的发生,函数原型中,第一个参数是一个等待队列头,即wait_queue_head_t 定义的变量,在LK 2.6 中使用init_waitqueue_head()函数初始化这个等待队列,然后第三个参数是设置超时,比如咱们这里设 了5s,这表示如果5 秒到了,那么函数会返回0,不管其它条件如何.第二个参数是一种等待的条件,或者说等 待的事件,如果条件满足了,那么函数也会返回,条件要是不满足,那么这个进程会进入睡眠,不过 interruptible 表明了信号可以把她中断.一旦进入睡眠,那么有三种情况,一种是wake_up 或者 wake_up_interruptible 函数被另一个进程执行,从而唤醒她,第二种是信号中断她,第三种就是刚才讲的 超时,时间到了,自然就会返回. 那么这里具体来说,先判断US_FLIDX_DISCONNECTING 这个flag 有没有设,如果没有设才进入睡眠, 否则就不需要浪费彼此的感情了.在进入睡眠之后,如果5 秒之内您没有把u 盘拔出来,那么5 秒一到,函数 返回0,继续往下走,如果您在5 秒之前拔出来了,那么后来咱们会讲,storage_disconnect()函数会执行, 她会设置US_FLIDX_DISCONNECTING 这个flag,并且她会调用wake_up(&us->scsi_scan_wait) 来唤醒这里睡眠的进程,告诉他:"别等了,哥们儿,你没那种命!"这样函数就会提前返回,不用等到5秒再返回 了.总之不管条件满不满足,5 秒之内肯定会返回,所以我们继续往下看. 910 行,看到PF_FREEZE 这个标记,有点眼熟,不过上次咱们看到的是PF_NOFREEZE,这些都是电源管 理的内容,无需理会.对于usb 设备,它可以进入suspend 状态,那么如果设置了这个flag,这里就让它进入 吧,于是有人问了,这个flag 我们从没设过啊,问题是这个flag 不一定非得是我们来设,要知道这里可能等 待 了一段时间的,(delay_use),既然等待了一段时间,就有可能被认为是要进入睡眠,总线上就不会有活动,于 是上头以为每人要理睬这个usb 设备了,于是就会为它设置进入suspend 的flag.特别的情况,你小子吃错 药了没事做,把delay_use 给设成1 光年,什么?光年不是时间单位?那好吧,那假设你把delay_use 设成 杨 过喜欢的十六年,那你说这个设备是不是该进入suspend 状态?或者说是不是该进入休眠状态?如果是,那 么调用内核提供的函数, refrigerator()去休眠. 117
917 行,再次判断设备有没有被断开,如果还是没有,那么执行scsi_scan_host()函数扫描,扫描然后就知 道这个host 或者说这个scsi 卡上面接了什么设备(虽然咱们这个只是模拟的scsi 卡),然后cat /proc/scsi/scsi 才能看到您的u 盘嘛不是.(scsi_scan_host()这里面发生了很多很多的故事,但这都是 scsi 那层的故事,咱们暂时先不去关注好不?) 然后922 行,complete_and_exit 函数,她和complete 函数还有一点点不一样,除了唤醒别人,还得结 束自己(exit).她的户口在kernel/exit.c 中: 842 NORET_TYPE void complete_and_exit(struct completion *comp, long code) 843 { 844 if (comp) 845 complete(comp); 846 847 do_exit(code); 848 } 所以这里会先检查&us->scsi_scan_done,在struct us_data 中,定义了一个成员struct completion scsi_scan_done,而在storage_probe()函数一开始为us 进行初始化的时候,调用了 init_completion(&us->scsi_scan_done)为us->scsi_scan_done 进行了初始化,如果此前 storage_disconnect()函数被调用了,那么她会调用wait_for_completion(&us->scsi_scan_done) 来进入睡眠并且等待咱们这里把她唤醒,此乃后话,暂且不表.待到分析storage_disconnect 的时刻再来 揭 晓.但是如果根本就没有人调用wait_for_completion(&scsi_scan_done),那么也就是说没有人睡眠,那 么这个complete 函数就什么也不做.然后do_exit()函数不用多说,内核提供的函数,结束进程.也就是说, 对于上面这个scan 的精灵进程,到这里她就会结束退出了.可以看出它是一个短命的守护进程,真的不知该 说天妒英才又还是该说红颜命薄呢.总之对于这个精灵进程来说,她的使命就是让你能在cat /proc/scsi/scsi 中看到你的U 盘,当然了,从此以后你在/dev 目录下面也就能看到你的设备了,比如 /dev/sda. 再来看父进程,也就是storage_probe(),在用kernel_thread()创建了usb_stor_scan_thread 之 后,一切正常的话,storage_probe()也走到了尽头了.1017 行,return 0 了.终于,这个不老的传说也终于 到了老的那一刻,一切都结束了,一切都烟消云散了.在这世上所有的事情都必须有个结束.--席慕蓉 彼岸花的传说(四) 江姐问:国民党推翻了么? 答:被阿扁推翻了,大家都成了好朋友. 董存瑞问:劳动人民还当牛做马么?答:都下岗了,不劳动了. 红色娘子军吴琼花来电话问:姐妹们都翻身得解放了吧? 答:思想解放了,都当小姐了. 杨子荣来电话问:土匪都剿灭了吧?答:都当公安了. 杨白劳来电话问:地主们都打倒了么? 答:都入党了. 马克思来电话问:资本家都消灭了么? 答:都进中央了. 上帝打电话问:看Linux 那些事儿的人都回帖了吗? 答:没回的都在去见你的路上. 如果你把上面这些对话写成程序,烧录到芯片上,那么当外界询问设备的时候,设备就知道该怎么回答.如 果你问姐妹们都翻身得解放了吧?设备就能回答你:思想解放了,都当小姐了.这就是scsi 设备的基本工作方 式.scsi 协议定义了一系列的命令.主机通过发送命令给设备来实现通信. 118 我们刚刚跟着storage_probe()几乎完整的走了一遍,貌似一切都该结束了,可是你不觉得你到目前为止 还根本没有看明白设备究竟怎么工作的吗?U 盘,不仅仅是usb 设备,还是”盘”,它还需遵守usb mass
- 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: 1023 dissociate_dev(us); 1024 retur
- 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,标志命令执行
922 complete_and_exit(&us->scsi_scan_done, 0);<br />
923 }<br />
显而易见,这里的daemonize()又会让咱们再ps -el 的命令输出中看到有usb-stor-scan 这么一个精<br />
灵进程.<br />
116<br />
903 行,delay_use 哪来的?同一文件中,最开始的地方,定义了一个静态变量,<br />
101 static unsigned int delay_use = 5;<br />
102 module_param(delay_use, uint, S_IRUGO | S_IWUSR);<br />
103 MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");<br />
设置了delay_use 为5,而module_param 是LK 2.6 提供的一个宏,使得delay_use 可以在模块被<br />
装载的时候设定.(如果不设,那么她自然就是这里的值5,表示使用一个新的设备之前等待5 秒延时.)为啥要<br />
delay 啊?不为啥,只是因为天上的星星会流泪,地上的玫瑰会枯萎.您插进去的u 盘也可能立刻又被您拔出<br />
来了,试想您插入以后一两秒之内又拔出来,那么咱们下面也不用耽误工夫再检测了嘛不是.<br />
903 行,判断delay_use>0,然后907 行,wait_event_interruptible_timeout(),它的第一个参数是<br />
us->scsi_scan_wait,请回答,us->scsi_scan_wait 是第一次露面吗?<br />
混迹外企这么多日子, 我可以很负责任的很有诚意的用英语语重心长的告诉你: The answer is no. 在<br />
storage_probe()函数的最初,在us 的初始化时,scsi_scan_wait 被初始化了.947<br />
行,init_waitqueue_head(&us->scsi_scan_wait),而在定义struct us_data 时,有一个成员就是<br />
scsi_scan_wait,即wait_queue_head_t scsi_scan_wait,这些都是什么意思呢?<br />
实际上wait_event_interruptible_timeout()是一个宏,它代表着Linux 中的一种等待机制,等待某个<br />
事件的发生,函数原型中,第一个参数是一个等待队列头,即wait_queue_head_t 定义的变量,在LK 2.6<br />
中使用init_waitqueue_head()函数初始化这个等待队列,然后第三个参数是设置超时,比如咱们这里设<br />
了5s,这表示如果5 秒到了,那么函数会返回0,不管其它条件如何.第二个参数是一种等待的条件,或者说等<br />
待的事件,如果条件满足了,那么函数也会返回,条件要是不满足,那么这个进程会进入睡眠,不过<br />
interruptible 表明了信号可以把她中断.一旦进入睡眠,那么有三种情况,一种是wake_up 或者<br />
wake_up_interruptible 函数被另一个进程执行,从而唤醒她,第二种是信号中断她,第三种就是刚才讲的<br />
超时,时间到了,自然就会返回.<br />
那么这里具体来说,先判断US_FLIDX_DISCONNECTING 这个flag 有没有设,如果没有设才进入睡眠,<br />
否则就不需要浪费彼此的感情了.在进入睡眠之后,如果5 秒之内您没有把u 盘拔出来,那么5 秒一到,函数<br />
返回0,继续往下走,如果您在5 秒之前拔出来了,那么后来咱们会讲,storage_disconnect()函数会执行,<br />
她会设置US_FLIDX_DISCONNECTING 这个flag,并且她会调用wake_up(&us->scsi_scan_wait)<br />
来唤醒这里睡眠的进程,告诉他:"别等了,哥们儿,你没那种命!"这样函数就会提前返回,不用等到5秒再返回<br />
了.总之不管条件满不满足,5 秒之内肯定会返回,所以我们继续往下看.<br />
910 行,看到PF_FREEZE 这个标记,有点眼熟,不过上次咱们看到的是PF_NOFREEZE,这些都是电源管<br />
理的内容,无需理会.对于usb 设备,它可以进入suspend 状态,那么如果设置了这个flag,这里就让它进入<br />
吧,于是有人问了,这个flag 我们从没设过啊,问题是这个flag 不一定非得是我们来设,要知道这里可能等<br />
待<br />
了一段时间的,(delay_use),既然等待了一段时间,就有可能被认为是要进入睡眠,总线上就不会有活动,于<br />
是上头以为每人要理睬这个usb 设备了,于是就会为它设置进入suspend 的flag.特别的情况,你小子吃错<br />
药了没事做,把delay_use 给设成1 光年,什么?光年不是时间单位?那好吧,那假设你把delay_use 设成<br />
杨<br />
过喜欢的十六年,那你说这个设备是不是该进入suspend 状态?或者说是不是该进入休眠状态?如果是,那<br />
么调用内核提供的函数, refrigerator()去休眠.<br />
117