`
dato0123
  • 浏览: 971005 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

前面已经说了,回到usb_stor_acquire_resources()函数中,返回了0。于是咱们终于回到了storage_probe()函数中来。

1008行,scsi_add_host()函数被执行,之前申请的us->host被作为参数传递给它,同时,intf->dev也被传递给它,这个东西是被用来注册sysfs的。前面已经说过,在scsi_host_alloc之后,必须执行scsi_add_host(),这样,SCSI核心层才能够知道有这么一个host存在。scsi_add_host()成功则返回0,否则返回出错代码。如果一切顺利,将走到1009行,别急,先把代码“贴”出来,这就是storage_probe()函数的最后一小段了:

1014

1015 /* Startup the thread for delayed SCSI-device scanning */

1016 th =kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");

1017 if (IS_ERR(th)) {

1018 printk(KERN_WARNING USB_STORAGE

1019"Unable to start the device-scanning thread\n");

1020 quiesce_and_remove_host(us);

1021 result = PTR_ERR(th);

1022 goto BadDevice;

1023 }

1024

1025 /* Take a reference to the hostfor the scanning thread and

1026 * count it among all the threads we have launched. Then

1027 * start it up. */

1028 scsi_host_get(us_to_host(us));

1029 atomic_inc(&total_threads);

1030 wake_up_process(th);

1031

1032 return 0;

1033

1034 /* We come here if there are anyproble ms */

1035 BadDevice:

1036 US_DEBUGP("storage_probe()failed\n");

1037 release_everything(us);

1038 return result;

1039 }

又一次见到了kthread_create,不需要更多解释,这里自然还是创建一个内核守护进程,只不过这次是usb_stor_scan_thread,而上次是usb_stor_control_thread。usb_stor_scan_thread()函数也是定义于drivers/usb/storage/usb.c中:

904 /* Thread to carry out delayed SCSI-devicescanning */

905 static int usb_stor_scan_thread(void * __us)

906 {

907 structus_data *us = (struct us_data *)__us;

908

909 printk(KERN_DEBUG

910 "usb-storage: device found at %d\n",us->pusb_dev->devnum);

911

912 /*Wait for the timeout to expire or for a disconnect */

913 if(delay_use > 0) {

914 printk(KERN_DEBUG "usb-storage: waitingfor device "

915"to settle before scanning\n");

916 retry:

917 wait_event_interruptible_timeout(us->delay_wait,

918 test_bit(US_FLIDX_DISCONNECTING,&us->flags),

919 delay_use * HZ);

920 if (try_to_freeze())

921 goto retry;

922 }

923

924 /*If the device is still connected, perform the scanning */

925 if (!test_bit(US_FLIDX_DISCONNECTING,&us->flags)) {

926

927 /* For bulk-only devices, determine the max LUN value */

928 if (us->protocol == US_PR_BULK &&

929!(us->flags & US_FL_SINGLE_LUN)) {

930 mutex_lock(&us->dev_mutex);

931 us->max_lun =usb_stor_Bulk_max_lun(us);

932 mutex_unlock(&us->dev_mutex);

933 }

934 scsi_scan_host(us_to_host(us));

935 printk(KERN_DEBUG "usb-storage: devicescan complete\n");

936

937 /* Should we unbind if no devices weredetected? */

938 }

939

940 scsi_host_put(us_to_host(us));

941 complete_and_exit(&threads_gone,0);

942 }

913行,delay_use哪来的?同一个文件中,最开始的地方,定义了一个静态变量:

110 static unsigned int delay_use = 5;

111 module_param(delay_use, uint, S_IRUGO |S_IWUSR);

112 MODULE_PARM_DESC(delay_use, "seconds todelay before using a new device");

设置了delay_use为5,而module_param是Linux Kernel 2.6提供的一个宏,使得delay_use可以在模块被装载时设定。(如果不设,那么它自然就是这里的值5,表示使用一个新的设备之前等待5秒延时。)为什么要延时啊?当插进去的U盘也可能立刻又被拔出来了,试想插入以后一两秒之内又拔出来,那么咱们下面也不用耽误工夫再检测了。

913行,判断delay_use>0,然后917行,wait_event_interruptible_timeout(),它的第一个参数是us->delay_wait。

在storage_probe()函数的最初,在us的初始化时,delay_wait被初始化了。975行,init_waitqueue_head(&us->delay_wait),而在定义structus_data时,有一个成员就是delay_wait,即wait_queue_head_t delay_wait,这些都是什么意思呢?

实际上wait_event_interruptible_timeout()是一个宏,它代表着Linux中的一种等待机制,等待某个事件的发生,函数原型中,第1个参数是一个等待队列头,即wait_queue_head_t定义的变量,在2.6内核中使用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秒之内肯定会返回,所以我们继续往下看。

920行,try_to_freeze(),这是电源管理的内容。

925行,再次判断设备有没有被断开,如果还是没有,那么执行scsi_scan_host()函数扫描,扫描然后就知道这个host或者说这个SCSI卡上面接了什么设备(虽然咱们这个只是模拟的SCSI卡),然后cat/proc/scsi/scsi才能看到您的U盘。

928行这一段,就是对于有多个LUN的设备,调用usb_stor_Bulk_max_lun()来获得max_lun。

然后941行,complete_and_exit函数,它和complete函数还有一点不一样,除了唤醒别人,还得结束自己(exit)。它在kernel/exit.c中:

1010 NORET_TYPE void complete_and_exit(structcompletion *comp, long code)

1011 {

1012 if (comp)

1013 complete(comp);

1014

1015 do_exit(code);

1016 }

这个函数中最重要的是do_exit()函数,不用多说,它是内核提供的函数,结束进程。也就是说,对于上面这个scan的精灵进程,到这里它就会结束退出了。可以看出它是一个短命的守护进程。总之对于这个精灵进程来说,它的使命就是让你能在cat /proc/scsi/scsi中看到你的U盘,当然了,从此以后你在/dev目录下面也就能看到你的设备了,比如/dev/sda。

再来看父进程,也就是storage_probe(),在用kernel_thread()创建了usb_stor_scan_thread之后,一切正常的话,storage_probe()也走到了尽头了。1032行,return 0了。终于,这个不老的传说也终于到了老的那一刻,一切都结束了,一切都烟消云散了。
分享到:
评论

相关推荐

    Linux那些事儿之我是USB(第2版)

    ### Linux那些事儿之我是USB(第2版)关键知识点概览 #### 一、书籍概述 - **核心主题**:本书主要围绕Linux内核中的USB子系统展开,深入剖析其工作原理和技术细节。 - **目标读者**:面向Linux初学者、驱动开发者...

    linux那些事儿之我是USB.zip

    本压缩包文件"linux那些事儿之我是USB.zip"包含了深入理解Linux USB驱动及内核相关知识的九个文档,包括Block层、EHCI主机控制器、HUB、PCI、SCSI硬盘、Sysfs、UHCI、USB core以及U盘。这些文档旨在提供一个系统性的...

    Linux那些事儿之我是USB

    ### Linux那些事儿之我是USB —— USB技术在Linux下的实现与探索 #### 引言 在探讨《Linux那些事儿之我是USB》这篇文章之前,我们先简单回顾一下文章的背景及主要内容。该文由一位自称对Linux并无太多好感的作者...

    Linux那些事儿

    Linux那些事儿之我是U盘 Linux那些事儿之我是Hub Linux那些事儿之我是USB Core Linux那些事儿之我是UHCI Linux那些事儿之我是EHCI控制器 Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是...

    Linux那些事儿之我是U盘.pdf

    Linux那些事儿之我是U盘-有书签版.pdf

    linux那些事儿我是USB.pdf

    在《Linux那些事儿之我是U盘》这篇诙谐幽默的技术文章中,作者以独特的视角介绍了Linux内核2.6版本中USB驱动的相关知识。通过轻松的叙述方式,让读者在轻松愉快的氛围中理解复杂的USB驱动原理及其在Linux系统中的...

    Linux那些事儿1-9合集

    读过《linux那些事儿之我是U盘》的人,都知道其风格,我就不多说了。 导读: linux那些事儿之我是U盘 linux那些事儿之我是HUB linux那些事儿之我是USB Core linux那些事儿之我是UHCI Linux那些事儿之我是EHCI主机控制...

    Linux那些事儿之我是U盘

    根据给定的信息,“Linux那些事儿之我是U盘”这一标题及描述主要聚焦于USB技术在Linux环境下的工作原理和技术细节。接下来,我们将基于这个主题展开深入探讨,涵盖USB技术的基本概念、USB在Linux系统中的实现机制...

    LINUX\Linux那些事儿系列

    3. **Linux那些事儿之我是U盘.pdf**: USB闪存驱动器,通常称为U盘,是常见的便携式存储设备。这部分可能讲述Linux如何识别、挂载和管理U盘,包括使用ums(USB Mass Storage)驱动程序,以及如何处理文件系统的读写...

    Linux那些事儿之全集

    导读.doc Linux那些事儿之我是Block层.pdf Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是Hub.pdf Linux那些事儿之我是USB_core.pdf Linux那些事儿之我是U盘.pdf等等 Linux那些事儿系列全在这里了

    Linux那些事儿系列.rar

    》包括《Linux那些事儿之我是Hub》、《Linux那些事儿之我是Sysfs》《Linux那些事儿之我是UHCI》、《Linux那些事儿之我是USB core》、《Linux那些事儿之我是U盘》,令人叹为观止的一个linux系列书籍。只能说,江山代...

    linux 那些事儿全集

    “Linux那些事儿之我是U盘.pdf”将关注通用串行总线(USB)闪存驱动器。这部分会解释Linux如何识别和处理USB闪存设备,包括文件系统的挂载和数据交换过程。 “Linux那些事儿之我是USB Core.pdf”涉及Linux内核的USB...

    linux的那些事儿全集

    Linux那些事儿之我是Block层 Linux那些事儿之我是EHCI主机控制器 Linux那些事儿之我是Hub Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Sysfs ...Linux那些事儿之我是U盘

    Linux那些事儿之我是XXX全集.rar

    "Linux那些事儿之我是XXX全集"这个资源集合,旨在深入剖析Linux内核中的关键组件,特别是与USB(通用串行总线)相关的部分,包括USB core、U盘、UHCI、PCI、SCSI硬盘、Block层和Hub等核心概念。这些文件将通过源代码...

    linux那些事儿之我是U盘

    ### Linux与USB存储设备——《Linux那些事儿之我是U盘》知识点提炼 #### 引言 本文基于一篇幽默且深入的教程《Linux那些事儿之我是U盘》,该文章通过作者的亲身经历和深入浅出的讲解,介绍了Linux操作系统中USB存储...

Global site tag (gtag.js) - Google Analytics