- Linux那些事儿之我是USB
- 肖林甫 肖季东 任桥伟
- 1169字
- 2020-08-27 00:52:23
11.面纱
前面说了那么多,才接触到usb_init。当然,我们并不需要去经历爱情、背叛与死亡,所需要经历的只是忍受前面大段大段的唠叨。
因为被__init给盯上,usb_init在做牛做马的辛勤劳作之后便不得不灰飞烟灭,不可谓不高尚,但它始终只能是我们了解面纱后面内容的跳板,是起点,却不是终点,我们不会为它停留太久,有太多的精彩和苦恼在等着我们。
866 if (nousb) { 867 pr info("%s: USB support disabled\n", usbcore_name); 868 return 0; 869 }
866行,知道C语言的人都会知道nousb是一个标志,只是不同的标志有不一样的精彩。这里的nousb是用来让我们在启动内核时通过内核参数去掉USB子系统的,Linux社会是一个很人性化的世界,它不会去逼迫我们接受USB,一切都只关乎我们自己的需要。不过我想我们一般是不会去指定nousb的吧,毕竟它那么的讨人喜爱。如果你真的指定了nousb,那它就只会幽怨地说一句“USB support disabled”,然后退出usb_init。
867行,pr_info只是一个打印信息的可变参数宏,即printk的变体,在include/linux/kernel.h中定义:
242 #define pr_info(fmt,arg...) \ 243 printk(KERN_INFO fmt,##arg)
1999年的ISO C标准里规定了可变参数宏,与函数语法类似,比如:
#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)
其中的“…”就表示可变参数,调用时,它们就会替代宏体里的__VA_ARGS__。GCC总是会显得特立独行一些,它支持更复杂的形式,可以给可变参数取个名字,比如:
#define debug(format, args...) fprintf (stderr, format, args)
有了名字之后,总是容易交流一些。是不是与pr_info比较接近了?除了“##”,它主要是针对空参数的情况。既然说是可变参数,那传递空参数也总是可以的。如果没有“##”,传递空参数时,比如:
debug ("A message");
展开后,里面的字符串后面会有一个多余的逗号,这个逗号你应该不会喜欢,而“##”则会使预处理器去掉这个多余的逗号。
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;
871行到897行是代码里的排比句,相似的init,不相似的内容,很显然都是在完成一些初始化,也是usb_init任劳任怨所付出的全部。
871行,电源管理方面的。如果在编译内核时没有打开电源管理,也就是说,没有定义CONFIG_PM,它就什么也不做。
874行,注册USB总线,只有成功地将USB总线子系统注册到系统中,我们才可以向这个总线添加USB设备。
877行,执行主机控制器相关的初始化。
880行,一个总线同时也是一个设备,必须单独注册,因为USB是通过快速串行通信来读写数据的,这里把它当做字符设备来注册。
883行~891行,都是usbfs相关的初始化。
892行,Hub的初始化。
895行,注册USB设备驱动,看清楚了,是USB device driver而不是USB driver。前面说过,一个设备可以有多个接口,每个接口对应不同的驱动程序,这里所谓的device driver对应的是整个设备,而不是某个接口。内核中的结构到处有,只是USB在这里格外多。
剩下的几行代码都是有关资源清除的,usb_init这个短短的函数在承载着我们的希望时戛然而止了,你的感觉是什么?笔者的感觉是:这哪是我能说得清楚的啊!它的每个分叉都更像是一个陷阱,黑黝黝的看不到底,但是已经没有回头的路。