11.面纱

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这个短短的函数在承载着我们的希望时戛然而止了,你的感觉是什么?笔者的感觉是:这哪是我能说得清楚的啊!它的每个分叉都更像是一个陷阱,黑黝黝的看不到底,但是已经没有回头的路。