Scsi - Index of
Scsi - Index of Scsi - Index of
384 us->srb->result); 385 us->srb->scsi_done(us->srb); 386 } else { 387 SkipForAbort: 388 US_DEBUGP("scsi command aborted\n"); 389 } 390 391 /* If an abort request was received we need to signal that 392 * the abort has finished. The proper test for this is 393 * the TIMED_OUT flag, not srb->result == DID_ABORT, because 394 * a timeout/abort request might be received after all the 112 395 * USB processing was complete. */ 396 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) 397 complete(&(us->notify)); 398 399 /* finished working on this command */ 400 SkipForDisconnect: 401 us->srb = NULL; 402 scsi_unlock(host); 403 404 /* unlock the device pointers */ 405 up(&(us->dev_semaphore)); 406 } /* for (;;) */ 407 408 /* notify the exit routine that we're actually exiting now 409 * 410 * complete()/wait_for_completion() is similar to up()/down(), 411 * except that complete() is safe in the case where the structure 412 * is getting deleted in a parallel mode of execution (i.e. just 413 * after the down() -- that's necessary for the thread-shutdown 414 * case. 415 * 416 * complete_and_exit() goes even further than this -- it is safe in 417 * the case that the thread of the caller is going away (not just 418 * the structure) -- this is necessary for the module-remove case. 419 * This is important in preemption kernels, which transfer the flow 420 * of execution immediately upon a complete(). 421 */ 422 complete_and_exit(&(us->notify), 0); 423 } 284 行,定义了一个Scsi_Host 的指针host,令她指向us->host,也就是刚刚用scsi_host_alloc() 申请的那个Scsi_Host 结构体变量. 292 行,daemonize("usb-storage"),其实,这句话才是真正创建精灵进程的,daemonize()函数来自
内核的核心位置,kernel/exit.c 中,她完成了这么一件事情,把一个普通的进程转换成为了精灵进程,不过 此 处咱们可以不去深究精灵进程的原理,甚至咱们可以认为这句话没有做任何事情,只是从此之后咱们ps命令 一看能够看到有一个叫做usb-storage 的进程.比如下面所看到的: localhost:~ # ps -el F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 4 S 0 1 0 0 76 0 - 195 - ? 00:00:02 init 1 S 0 2 1 0 -40 - - 0 migrat ? 00:00:00 migration/0 1 S 0 3 1 0 94 19 - 0 ksofti ? 00:00:00 ksoftirqd/0 1 S 0 18 1 0 70 -5 - 0 worker ? 00:00:00 events/0 1 S 0 26 1 0 71 -5 - 0 worker ? 00:00:00 khelper 113 1 S 0 27 1 0 70 -5 - 0 worker ? 00:00:00 kthread 1 S 0 45 27 0 72 -5 - 0 worker ? 00:00:00 kacpid 1 S 0 229 27 0 80 0 - 0 pdflus ? 00:00:00 pdflush 1 S 0 230 27 0 75 0 - 0 pdflus ? 00:00:00 pdflush 1 S 0 231 1 0 76 0 - 0 kswapd ? 00:00:00 kswapd0 1 S 0 961 27 0 70 -5 - 0 scsi_e ? 00:00:00 scsi_eh_0 1 S 0 1033 27 0 70 -5 - 0 scsi_e ? 00:00:00 scsi_eh_1 1 S 0 1045 27 0 71 -5 - 0 scsi_e ? 00:00:00 scsi_eh_2 1 S 0 1047 27 0 70 -5 - 0 worker ? 00:00:00 scsi_wq_2 5 S 0 1262 1 0 72 -4 - 1774 - ? 00:00:02 udevd 1 S 0 1939 27 0 70 -5 - 0 hub_th ? 00:00:00 khubd 1 S 0 7804 27 0 70 -5 - 0 scsi_e ? 00:00:00 scsi_eh_3 1 S 0 7805 27 0 70 -5 - 0 - ? 00:00:00 usb-storage 4 S 0 13905 13902 0 75 0 - 2430 wait pts/1 00:00:00 bash 0 R 0 19098 13905 0 77 0 - 821 - pts/1 00:00:00 ps 显然,您在终端按ctrl-c 是不可能中止这个usb-storage 进程的.这是精灵进程诸多特性中的一个,她运 行于后台.试一下kill -9 加进程号,看你能杀死她不?(系统崩溃了我可不负责哦...) 294行,这里为目前的进程设置一个flag,PF_NOFREEZE,在整个内核代码中,这个flag 也只出现过几次. 这个flag 是与电源管理相关的,2.6 的内核为了实现与Windows 相似的一个功能,Hibernate,也就是"冬 眠",(别说您不知道,Windows 关机选项里面有"关机","重启","注销","Stand by",以及"Hibernate").在 内核编译菜单里面,Power managerment options 中,有一个选项Software Suspend,也就是内核编译 选项中的CONFIG_SOFTWARE_SUSPEND,选择了她使得机器可以被suspended.显然咱们不用care 她. 但是这里之所以要设置这个flag,是因为suspend 要求把内存里的冬冬写到磁盘上,而一个进程设置了 这个flag 就表明它在suspend 的时候不会被冻住,用行话来讲就是,they’re not refrigerated during a suspend.freeze 就是冷冻,冻住的意思,过去分词frozen 是形容词,冻结的,冰冻的,其实就是让进程睡眠. 所以总的来说,这里的做法就是说,即使系统suspend 了,这个进程,或者准确地说,这个内核线程,也不应该 进入睡眠. 要执行这两个操作需要执行lock_kernel()/unlock_kernel()这一对函数.然后299 行,执行complete 唤醒前面那节的父进程.而子进程并不退出,她继续行走,她无怨无悔的行走,只不过余秋雨先生是为追寻人 类文明足迹而进行的域外旅程,而此处子进程(执)行的她对内核的守护.她像天使一般,守护着心爱的人. 于是咱们也继续跟着她行走,299 行, complete(&(us->notify)),这正是和刚才在父进程里看到的那句 使进程进入睡眠的wait_for_completion(&(us->notify))相对应,这里自然是唤醒父进程,我们先继续看
- 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: 341 } 342 343 /* reject if target !
- 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
384 us->srb->result);<br />
385 us->srb->scsi_done(us->srb);<br />
386 } else {<br />
387 SkipForAbort:<br />
388 US_DEBUGP("scsi command aborted\n");<br />
389 }<br />
390<br />
391 /* If an abort request was received we need to signal that<br />
392 * the abort has finished. The proper test for this is<br />
393 * the TIMED_OUT flag, not srb->result == DID_ABORT, because<br />
394 * a timeout/abort request might be received after all the<br />
112<br />
395 * USB processing was complete. */<br />
396 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags))<br />
397 complete(&(us->notify));<br />
398<br />
399 /* finished working on this command */<br />
400 SkipForDisconnect:<br />
401 us->srb = NULL;<br />
402 scsi_unlock(host);<br />
403<br />
404 /* unlock the device pointers */<br />
405 up(&(us->dev_semaphore));<br />
406 } /* for (;;) */<br />
407<br />
408 /* notify the exit routine that we're actually exiting now<br />
409 *<br />
410 * complete()/wait_for_completion() is similar to up()/down(),<br />
411 * except that complete() is safe in the case where the structure<br />
412 * is getting deleted in a parallel mode <strong>of</strong> execution (i.e. just<br />
413 * after the down() -- that's necessary for the thread-shutdown<br />
414 * case.<br />
415 *<br />
416 * complete_and_exit() goes even further than this -- it is safe in<br />
417 * the case that the thread <strong>of</strong> the caller is going away (not just<br />
418 * the structure) -- this is necessary for the module-remove case.<br />
419 * This is important in preemption kernels, which transfer the flow<br />
420 * <strong>of</strong> execution immediately upon a complete().<br />
421 */<br />
422 complete_and_exit(&(us->notify), 0);<br />
423 }<br />
284 行,定义了一个<strong>Scsi</strong>_Host 的指针host,令她指向us->host,也就是刚刚用scsi_host_alloc()<br />
申请的那个<strong>Scsi</strong>_Host 结构体变量.<br />
292 行,daemonize("usb-storage"),其实,这句话才是真正创建精灵进程的,daemonize()函数来自