Linux那些事儿之我是Hub(2)
莎士比亚曾经说过,不懂hub是怎么工作的就等于不知道usb设备驱动是怎么工作的.这句话一点没错,因为usb设备的初始化都是hub这边发起的,通常我们写usb设备驱动程序都是在已经得到了一个struct usb_interface指针的情况下开始probe工作,可是我要问你,你的struct usb_interface从哪来的?你以为你的设备天生丽质?长得比较帅?一插入usb口就有了?如果有人说是的,那么我只能说,相信这个人的嘴,不如相信世上有鬼!老实说,要想知道从usb设备插入usb口的那一刻开始,这个世界发生了什么,你必须知道hub是怎么工作的,Linux中hub驱动程序是怎么工作的.
要说usb hub,那得从Root hub说起.什么是Root hub?冤有头债有主,不管你的电脑里连了多少个usb设备,她们最终是有根的,她们不会像孙猴那样从石头里蹦出来的,不会像北京电视台纸包子的新闻凭空就可以造出来.所有的usb设备最终都是连接到了一个叫做Root Hub的冬冬上,或者说所有的根源都是从这里开始的.Root Hub上可以连接别的设备,可以连接U盘,可以连接usb鼠标,同样也可以连接另一个hub.所谓hub,就是用来级连.但是普通的hub,她一头接上级hub, 另一头可以有多个口,多个口就可以级连多个设备,也可以只有一个口,一个口的就像我们宿舍里常用的那种延长线.而Root Hub呢?她比较特殊,她当然也是一种usb设备,但是她属于一人之下万人之上的角色,她只属于被Host Controller,换言之,通常做芯片的同志们会把Host Controller和Root Hub集成在一起.特别是PC主机上,通常你就只能看到接口,看不到Root Hub,因为她躺在Host Controller的怀里.这一对狗男女躲在机箱里面,你当然看不到.下面这张图看得很清楚,
其中的那个host hub其实就是root hub.当然,我们应该更加准备的评价host和root hub的关系,她们是双生花,不会残酷地吸纳彼此的幸福,只会一直不离不弃地在风中相依,直到凋零…(虽然言论自由,但是我必须声明,我绝对没有影射最近牺牲在车里的徐新贤书记以及那个和他一起裸死在车里的妇联主席潘丽航的意思,请不要误会,我个人还是很欣赏这种死了都要爱的境界的,这种追求真爱,追求自由的思想正是整个开源社区所推崇的,也正是开源精神的灵魂所在,我顶!)
Ok,别扯远了,继续回来,既然root hub享有如此特殊的地位,那么很显然,整个usb子系统得特别的爱给特别的你,一开始就会要初始化hub.所以我们从usb子系统的初始化代码开始看起.也就是usb的核心代码.来自drivers/usb/core/usb.c:
938 subsys_initcall(usb_init);
939 module_exit(usb_exit);
很显然,这样两行正是Linux中usb子系统的初始化代码,这里我们看到一个subsys_initcall,它也是一个宏,我们可以把它理解为module_init,只不过因为这部分代码比较核心,开发者们把它看作一个子系统,而不仅仅是一个模块,这也很好理解,usbcore这个模块它代表的不是某一个设备,而是所有usb设备赖以生存的模块,Linux中,像这样一个类别的设备驱动被归结为一个子系统.比如pci子系统,比如scsi子系统,基本上,drivers/目录下面第一层的每个目录都算一个子系统,因为它们代表了一类设备.subsys_initcall(usb_init)的意思就是告诉我们usb_init是我们真正的初始化函数,而usb_exit()将是整个usb子系统的结束时的清理函数.于是我们就从usb_init开始看起,
860 /*
861 * Init
862 */
863 static int __init usb_init(void)
864 {
865 int retval;
866 if (nousb) {
867 pr_info("%s: USB support disabled\n", usbcore_name);
868 return 0;
869 }
870
871 retval = ksuspend_usb_init();
872 if (retval)
873 goto out;
874 retval = bus_register(&usb_bus_type);
875 if (retval)
876 goto bus_register_failed;
877 retval = usb_host_init();
878 if (retval)
879 goto host_init_failed;
880 retval = usb_major_init();
881 if (retval)
882 goto major_init_failed;
883 retval = usb_register(&usbfs_driver);
884 if (retval)
885 goto driver_register_failed;
886 retval = usb_devio_init();
887 if (retval)
888 goto usb_devio_init_failed;
889 retval = usbfs_init();
890 if (retval)
891 goto fs_init_failed;
892 retval = usb_hub_init();
893 if (retval)
894 goto hub_init_failed;
895 retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
896 if (!retval)
897 goto out;
898
899 usb_hub_cleanup();
900 hub_init_failed:
901 usbfs_cleanup();
902 fs_init_failed:
903 usb_devio_cleanup();
904 usb_devio_init_failed:
905 usb_deregister(&usbfs_driver);
906 driver_register_failed:
907 usb_major_cleanup();
908 major_init_failed:
909 usb_host_cleanup();
910 host_init_failed:
911 bus_unregister(&usb_bus_type);
912 bus_register_failed:
913 ksuspend_usb_cleanup();
914 out:
915 return retval;
916 }
2854 int usb_hub_init(void)
2855 {
2856 if (usb_register(&hub_driver) < 0) {
2857 printk(KERN_ERR "%s: can't register hub driver\n",
2858 usbcore_name);
2859 return -1;
2860 }
2861
2862 khubd_task = kthread_run(hub_thread, NULL, "khubd");
2863 if (!IS_ERR(khubd_task))
2864 return 0;
2865
2866 /* Fall through if kernel_thread failed */
2867 usb_deregister(&hub_driver);
2868 printk(KERN_ERR "%s: can't start khubd\n", usbcore_name);
2869
2870 return -1;
2871 }
最后,补充一条背景知识介绍,本年度感动中国新闻之一:
杭州信息网最新消息:临安市清凉峰镇党委书记,优秀共产党员徐新贤日前因公牺牲.徐新贤书记因忙于公务,日夜操劳过度,终因体力不支,牺牲在小车上,同时牺牲的还有该镇优秀妇女干部一名.据悉,徐新贤书记和该名妇女干部在小汽车里谈论公务,因汽油燃尽,空调断电,车内闷热严重,车子又是停在车库里,二人为了解热,脱光了衣服裤子,还在坚持谈公事,一直谈到牺牲为止.有这样认真负责的好书记,清凉峰镇的老百姓是幸福的.书记时刻为人民办事,牺牲前还在亲自做妇女工作,他的事迹,人们都记在了心里.
一路走来的兄弟们不会对这样一段代码陌生,是不是有一种似曾相识燕归来的感觉?没有?没有就没有吧,同是天涯堕落人,相逢何必曾相识.好家伙,一堆的函数,每一个都够我看的了.写代码的无非就是想吓唬吓唬我,共产党员死都不怕,这点小事还能吓住我们吗? 我们不用仔细看,扫一眼就能发现,许多名叫*init*的函数,很显然,就是做一些初始化.其中我们要关注的是hub,它也是在这里初始化的,换言之,随着usb core的初始化,hub也就开始了她的初始化之路.这就是1490行,usb_hub_init()函数得到调用.这个函数来自drivers/usb/core/hub.c:
Linux那些事儿之我是Hub(2)相关推荐
- Linux那些事儿之我是Hub(9)While You Were Sleeping(二)
老实说,从函数一个开始的598行直到627行都没有什么可说的.其中需要一提的是,606行,调用usb_buffer_alloc()申请内存,赋给hub->buffer.614行,调用kmallo ...
- Linux那些事儿之我是Hub(4)
这一节我们讲队列. 从前在乡下的时候是不用排队的,村里的人们都很谦让,而且人本来又不多.后来到了县城里,县城里不大,大家去走亲戚去串门去逛街不用坐车不用排队,除了街上的游戏厅人多一点以外,别的地方人都 ...
- 【转】Linux那些事儿之我是Hub(7)蝴蝶效应
朋友,你相信,一只蝴蝶在北京拍拍翅膀,将使得纽约几个月后出现比狂风还厉害的龙卷风吗?看过那部经典的影片蝴蝶效应的朋友们一定会说,这不就是蝴蝶效应吗.没错.蝴蝶效应其实是混沌学理论中的一个概念.它是指对 ...
- Linux那些事儿之我是Hub(1)跟我走吧,现在就出发
最早知道hub是在大学里,复旦的4人间宿舍,条件真好,每个人一张书桌,书桌下面一个网口,但是有时候网口坏了,那可急死人了,要知道当初我们买电脑初衷虽说是为了学习C语言,可是买了之后,C倒是没学,先学了 ...
- Linux那些事儿之我是Hub(25)不说代码说理论
当女作家们越来越多的使用下半身来告诉我什么是文学的时候,当模特们越来越多的使用裸体来告诉我什么是人体艺术的时候,我开始对这个社会困惑了,当行为艺术家们越来越多的使用垃圾堆砌来告诉我什么是波谱的时候,当 ...
- Linux那些事儿之我是Hub(19)八大重量级函数闪亮登场(三)
在开始第三个函数前,2492行至2494行还有三行代码,对udev中的speed,bus_mA,level进行赋值. 先说一下,bus_mA,struct usb_device中的成员,unsigne ...
- Linux设备之我是usb,linux那些事儿之我是usb
linux那些事儿之我是usb,复旦大学教授肖林甫先生给学生们解说的linux操作系统的一些硬件驱动开发的事儿. 内核说明: 我是U盘 说的是2.6.10的内核 我是Sysfs 说的是2.6.10的内 ...
- Linux系统USB驱动目录,Linux那些事儿之我是USB 目录
目录 第1篇 Linux那些事儿之我是USB Core 1.引子 2 2.它从哪里来 2 3.PK 3 4.漫漫辛酸路 3 5.我型我秀 4 6.我是一棵树 5 7.我是谁 9 8.好戏开始了 11 ...
- 读书笔记《Linux那些事儿之我是USB》
第一篇:Linux那些事儿之我是USB Core USB诞生于inel 产生是为了解决前期计算机并口串口的问题,实现一种解决速度,扩展性,易用性的通信方式. 速度:usb2.0高速模式,480MB/s ...
最新文章
- [转]启动Tomcat提示:指定的服务未安装
- 深入浅出 Java CMS 学习笔记
- 深入理解 Node.js 中 EventEmitter源码分析(3.0.0版本)
- android多线程实现计时器,方法一、使用Handler和Thread(线程)实现定时器
- 持久化策略RDB和AOF的简单理解
- H.264(MPEG)-4AVC
- 中了勒索病毒怎么办|文件解密|文件恢复
- 小米蓝牙键盘怎么连接_【米物蓝牙双模键盘使用总结】连接|操作|按键_摘要频道_什么值得买...
- mysql驱动加载失败怎么办_为什么mysql加载驱动会报错呢输出的结果是加载驱动失败...
- 获得bat的运行目录
- android7.0版本适配(一):应用间文件文件共享——FileProvider
- opencv3.4.4 +contrib模块在win10+vs2017的编译和配置
- #Vue3篇:watch、watchEffect、watchPostEffect、watchSyncEffect的区别
- 1-9DCL语言与提权逻辑
- Elastic开源社区:开发者招募
- c语言中余数取整,C 逻辑运算, 移位运算 , 取整 , 取模(取余)
- 挨踢部落故事汇(20):Android程序员的十大转型之路
- Java java.lang.ArithmeticException: Rounding necessary问题解决
- Android 点击查看大图(长按保存图片)
- 坐在家里攀登珠峰!《Everest VR》带你看VR旅游冒险内容的未来