【转】Linux那些事儿 之 戏说USB(38)接口的驱动

来源:互联网 发布:python decode 参数 编辑:程序博客网 时间:2024/04/28 09:38

从上节的上节我们已经知道,usb_generic_driver在自己的生命线里,以一己之力将设备的各个接口送给了linux的设备模型,让usb总线的match函数,也就是usb_device_match,在自己的那条驱动链表里为它们寻找一个合适的接口驱动程序。现在让咱们轻声的问一句,这些接口驱动都从哪里来?()

这 就要说到每个玩儿linux的人都会知道的那几个著名的命令insmod,modprobe,rmmod。你insmod或modprobe驱动的时候, 经过一个曲折的过程,会调用到你驱动里的那个xxx_init函数,进而去调用usb_register()将你的驱动提交给设备模型,添加到usb总线 的驱动链表里。你rmmod驱动时候,同样经过一个曲折的过程之后,调用到你驱动里的那个xxx_cleanup函数,进而调用 usb_deregister()将你的驱动从usb总线的驱动链表里删除掉。现在就看看include/linux/usb.h里定义的 usb_register函数
916 static inline int usb_register(struct usb_driver *driver)
917 {
918         return usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
919 }
看到这个函数,让人不得不感叹一下,现在什么都要讲究包装,明星们是靠绯闻去包装,这不,何洁大妹子在玩过走光,整容等等之后,还不怎么的过瘾,又玩起了绯闻。内核里也免不了这个俗,注册个驱动也要包装个两层,不过这个包装不是为了出名,而是方便大伙儿的。
本 来在两年以前是没这么多道道儿的,也没有usb_register_driver这么一个函数,只有个usb_register(),它直接就把啥事儿都 做了。而且那个时候struct usb_driver结构里还有一个有名的owner字段,每个在那个岁月里写过usb驱动的人都会认得它,并且都会毫无犹豫的将它设置为 THIS_MODULE。但是经过岁月的洗礼,在早先贴出来的struct usb_driver结构内容里,你发现owner已经无影无踪了。要搞清楚这个历史变迁的来龙去脉,你得知道这个owner和THIS_MODULE都 代表了什么。
从 那个时代走过来的人,都应该知道owner是一个struct module *类型的结构体指针,现在告诉你的是每个struct module结构体在内核里都代表了一个内核模块,就像十七大里的每个代表都代表了一批人,至于代表了什么人,选他们的人才知道,同样,每个struct module结构体代表了什么模块,对它进行初始化的模块才知道。当然,初始化这个结构不是写驱动的人该做的事,是在刚才略过的那个从insmod或 modprobe到你驱动的xxx_init函数的曲折过程中做的事。insmod命令执行后,会调用kernel/module.c里的一个系统调用 sys_init_module,它会调用load_module函数,将用户空间传入的整个内核模块文件创建成一个内核模块,并返回一个struct module结构体,从此,内核中便以这个结构体代表这个内核模块。
再看看THIS_MODULE宏是什么意思,它在include/linux/module.h里的定义是
85 #define THIS_MODULE (&__this_module)
是 一个struct module变量,代表当前模块,与那个著名的current有几分相似,可以通过THIS_MODULE宏来引用模块的struct module结构,比如使用THIS_MODULE->state可以获得当前模块的状态。现在你应该明白为啥在那个岁月里,你需要毫不犹豫毫不迟 疑的将struct usb_driver结构里的owner设置为THIS_MODULE了吧,这个owner指针指向的就是你的模块自己。那现在owner咋就说没就没了 那?这个说来可就话长了,咱就长话短说吧。不知道那个时候你有没有忘记过初始化owner,反正是很多人都会忘记,大家都把注意力集中到probe、 disconnect等等需要动脑子的角色上面了,这个不需要动脑子,只需要花个几秒钟指定一下的owner反倒常常被忽视,这个就是容易得到的往往不去 珍惜,不容易得到的往往日日思量着去争取。于是在2006年的春节前夕,在咱们都无心工作无心学习等着过春节的时候,Greg坚守一线,去掉了 owner,于是千千万万个写usb驱动的人再也不用去时刻谨记初始化owner了。咱们是不用设置owner了,可core里不能不设置,struct usb_driver结构里不是没有owner了么,可它里面嵌的那个struct device_driver结构里还有啊,设置了它就可以了。于是Greg同时又增加了usb_register_driver()这么一层, usb_register()可以通过将参数指定为THIS_MODULE去调用它,所有的事情都挪到它里面去做。反正usb_register()也是 内联的,并不会增加调用的开销。现在是时机看看usb_register_driver函数了
719 /**
720 * usb_register_driver - register a USB interface driver
721 * @new_driver: USB operations for the interface driver
722 * @owner: module owner of this driver.
723 * @mod_name: module name string
724 *
725 * Registers a USB interface driver with the USB core. The list of
726 * unattached interfaces will be rescanned whenever a new driver is
727 * added, allowing the new driver to attach to any recognized interfaces.
728 * Returns a negative error code on failure and 0 on success.
729 *
730 * NOTE: if you want your driver to use the USB major number, you must call
731 * usb_register_dev() to enable that functionality. This function no longer
732 * takes care of that.
733 */
734 int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
735                         const char *mod_name)
736 {
737         int retval = 0;
738
739         if (usb_disabled())
740                 return -ENODEV;
741
742         new_driver->drvwrap.for_devices = 0;
743         new_driver->drvwrap.driver.name = (char *) new_driver->name;
744         new_driver->drvwrap.driver.bus = &usb_bus_type;
745         new_driver->drvwrap.driver.probe = usb_probe_interface;
746         new_driver->drvwrap.driver.remove = usb_unbind_interface;
747         new_driver->drvwrap.driver.owner = owner;
748         new_driver->drvwrap.driver.mod_name = mod_name;
749         spin_lock_init(&new_driver->dynids.lock);
750         INIT_LIST_HEAD(&new_driver->dynids.list);
751
752         retval = driver_register(&new_driver->drvwrap.driver);
753
754         if (!retval) {
755                 pr_info("%s: registered new interface driver %s/n",
756                         usbcore_name, new_driver->name);
757                 usbfs_update_special();
758                 usb_create_newid_file(new_driver);
759         } else {
760                 printk(KERN_ERR "%s: error %d registering interface "
761                         "       driver %s/n",
762                         usbcore_name, retval, new_driver->name);
763         }
764
765         return retval;
766 }
这 函数和前面见过的usb_register_device_driver长的很相,你如果是从那里一路看过来的话,不用俺说什么,你都会明明白白它的意 思。不过,本着与人为善的态度,俺还是要简单提一点,for_devices在742行设置成了0,有了这行,match里的那个is_usb_device_driver把 门儿的才不会把它当成设备驱动放过去。然后就是在752行将你的驱动提交给设备模型,从而添加到usb总线的驱动链表里,从此之后,接口和接口驱动就可以 通过usb总线的match函数传情达意眉来眼去。当然,usb的世界里不存在什么一见钟情,也不相信什么一见钟情,因为你不能一眼看出对方挣多少钱,它 们要想对上眼,都得严格的满足对方的条件,我们可能那样无条件爱另一人吗?陌陌生生,他又没生我,我又没生他。


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1860387


[收藏到我的网摘]  [发送Trackback]  fudan_abc发表于2007年11月01日 00:10:00




特别推荐:
想在这里投放广告?点击查看详情
关闭
  • 主机完全DIY,域名免费试用
    时代互联100M主机 216元/年 驱动
  • 加拿大·达内专注高端it培训先就业后付款
    四大技术体系四门热点技术,国内最强大的专家授课组合 学员就业IBM,微软,华为等名企年薪7-20万不等
  • C#的多线程能力
    翻译文章
  • 免费体验张孝祥Java基础课程
    夯实基础往前跑 1万元的线下课程现在几百元就可以得到
  • 如何通过管理活动内容提高应用程序的安全性
    借助活动内容过滤避开Web 2.0应用程序常见攻击
上一篇: Linux那些事儿之我是UHCI(14)一个函数引发的故事(五) | 下一篇: Linux那些事儿 之 戏说USB(37)字符串描述符

评论

#  alaiyeshi 发表于2007-11-01 14:42:56  IP: 218.241.187.*
博主
除了U盘和HUB以外,其他的合集有写好了的么?
能把你的写作计划列一下么?
这样阅读计划好安排

BTW:
貌似在空间上,我们不远,我得天天下了城铁坐375,经常遇到西直门口拉黑车的大叔

#  fudan_abc 发表于2007-11-01 14:53:06  IP: 222.76.164.*
除了U盘和HUB,usb core(就是戏说USB,完成后出PDF的时候会把名字改了)过两天就完工了,UHCI也在进行中。
阅读顺序上,博客导读里有,建议是按照U盘、HUB、usb core、UHCI/EHCI这样的顺序,每一部分都比前一部分深入,按照顺序阅读更方便理解。
至于之后的写作计划,差不多就是按照博客导读里边儿的。

#  alaiyeshi 发表于2007-11-01 15:57:49  IP: 218.241.187.*
主要是我可能不是很有时间看网页了
所以一直想找所有的PDF文档。呵呵

#  nshfarmer 发表于2007-11-03 17:10:43  IP: 58.60.231.*
多谢博主
我是初涉linux大山的新手。现在是做C软件开发,自己学习linux下开发。
你的文字写的真好,向您学习!

请教了:为什么你不建议读那个0.11版本的linux源码分析,那本书的pdf我有,看起来写的很详细,我也想看新的,可是新的代码量太大了,你认为有必要看那些老代码吗?

我也很困惑,我是打算做linux下嵌入式开发之类的工作,本不想设计到x86汇编。
现在正在打基础,学习shell编程,gcc gdb vim的使用, makefile的读写。感觉东西真是多啊
可否指点一下,向我这种要怎么去学吗?看linux代码要怎样看呢?

#  fudan_abc 发表于2007-11-03 22:42:40  IP: 121.207.129.*
赵 炯那本书的电子版我也快速扫了一下,你如果刚开始接触内核从那本书里找找感觉也未尝不可,不过我建议还是不要看太仔细了,你就是看的再细看完也是忘差不多 的,而且它里边的东东和现在的内核当然是不能够相比的。其实研究内核最经典的几本书无外乎那几本,网上很多大侠们都会推荐,首推的当然就是linux内核 设计与实现,偏实践的就是LDD3,另外有两本是讲WM的,和那本讲网络的understanding linux network internals。如果想整体的了解内核的各个方面就可以先看几遍linux内核设计与实现,赵炯那本我是觉得不易看的太仔细,过一遍就可以了。不能因 为新的代码量大就去钻古老的,你只需要对内核整体上有个概念,然后对自己比较感兴趣的某个子系统比如网络什么的钻下去就可以了,即使写内核的哥们儿也不可 能都懂的。

但是学习内核,我个人感觉是不能只钻内核,不然很可能就是觉得书也看了几本怎么是看了就忘看了就忘,linux是一个整体工 程,首先要对它使用操作整个体系熟悉,我建议是从上到下的学习,就是先是使用,GUI,shell等,然后是WM,xserver等,然后是驱动,接着是 内核。很多基础的东西,比如gdb,makefile等等都是需要在使用中学习的,概念什么的可以先熟悉一下,然后用到了可以去参考,其实这跟咱们学其它 东西也一样。

说大实话,我是真的不愿建议一开始就接触内核。当然这只是我个人看法,呵呵,仅供参考。
 
原创粉丝点击