《Linux那些事儿之我是USB》我是U盘(26)彼岸花的传说(三)--总结

usb_stor_probe1
{
init_waitqueue_head(&us->delay_wait);
INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork);
}


usb_stor_probe2
{
queue_delayed_work(system_freezable_wq, &us->scan_dwork,delay_use * HZ);
}


static void usb_stor_scan_dwork(struct work_struct *work)
{

  if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {                                      
        mutex_lock(&us->dev_mutex);                                                                             
        us->max_lun = usb_stor_Bulk_max_lun(us);  //对于有多个LUN的设备,调用usb_stor_Bulk_max_lun()来获得max_lun。                                               mutex_unlock(&us->dev_mutex);                                                                           
    }
scsi_scan_host(us_to_host(us)); 
//执行scsi_scan_host()函数扫描,扫描然后就知道这个host或者说这个SCSI卡上面接了什么设备(这个只是模拟的SCSI卡),然后cat/proc/scsi/scsi才能看到您的U盘。

}
 
static void get_transport(struct us_data *us)
{
     case USB_PR_BULK:                                                         
        us->transport_name = "Bulk";
        us->transport = usb_stor_Bulk_transport;
        us->transport_reset = usb_stor_Bulk_reset;
        break;
  //us的transport_name被赋值为“Bulk”
transport被赋值为usb_stor_Bulk_transport
transport_reset被赋值为usb_stor_Bulk_reset。其中我们最需要记住us的成员transport和transport_reset是两个函数指针。这两个函数叫“钩子”函数。这两个赋值我们需要牢记,日后我们一定会用到它们,因为这正是我们真正的数据传输时调用的东西。



int usb_stor_Bulk_reset(struct us_data *us)
{
    return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
                 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
                 0, us->ifnum, NULL, 0);
}
EXPORT_SYMBOL_GPL(usb_stor_Bulk_reset);


static int usb_stor_reset_common(struct us_data *us,
        u8 request, u8 requesttype,
        u16 value, u16 index, void *data, u16 size)
{
  wait_event_interruptible_timeout(us->delay_wait,
            test_bit(US_FLIDX_DISCONNECTING, &us->dflags),
            HZ*6);
}
//wait_event_interruptible_timeout()是一个宏,它代表着Linux中的一种等待机制,等待某个事件的发生,函数原型中,第1个参数是一个等待队列头,即wait_queue_head_t定义的变量,在内核中使用init_waitqueue_head()函数初始化这个等待队列,然后第3个参数是设置超时。比如这里设了5秒,这表示如果5秒到了,那么函数会返回0,不管其他条件如何。第2个参数是一种等待的条件,或者说等待的事件,如果条件满足了,那么函数也会返回,条件要是不满足,那么这个进程会进入睡眠,不过interruptible表明了信号可以把它中断。
 
一旦进入睡眠,那么有三种情况:一种是wake_up或者wake_up_interruptible函数被另一个进程执行,从而唤醒它,第二种是信号中断它,第三种就是刚才讲的超时,时间到了,自然就会返回。

先判断US_FLIDX_DISCONNECTING这个flag有没有设置,如果没有设置才进入睡眠。在进入睡眠之后,如果5秒之内没有把U盘拔出来,那么5秒一到,函数返回0,继续往下走,如果在5秒之前拔出来U盘了,那么后来咱们会讲,storage_disconnect()函数会执行,它会设置US_FLIDX_DISCONNECTING这个flag,并且它会调用wake_up(&;us->scsi_scan_wait)来唤醒这里睡眠的进程,这样函数就会提前返回,不用等到5秒再返回了。总之不管条件满不满足,5秒之内肯定会返回,所以我们继续往下看。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux技术芯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值