Linux那些事儿 之 戏说USB(34)接口的驱动
生活随笔
收集整理的這篇文章主要介紹了
Linux那些事儿 之 戏说USB(34)接口的驱动
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
從上節的上節我們已經知道,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函數
本來在兩年以前是沒這么多道道兒的,也沒有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/export.h里的定義是
這就要說到每個玩兒linux的人都會知道的那幾個著名的命令insmod,modprobe,rmmod。你insmod或modprobe驅動的時候,經過一個曲折的過程,會調用到你驅動里的那個xxx_init函數,進而去調用usb_register()將你的驅動提交給設備模型,添加到usb總線的驅動鏈表里。你rmmod驅動時候,同樣經過一個曲折的過程之后,調用到你驅動里的那個xxx_cleanup函數,進而調用usb_deregister()將你的驅動從usb總線的驅動鏈表里刪除掉。現在就看看include/linux/usb.h里定義的usb_register函數
#define usb_register(driver) \usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)看到這個函數,讓人不得不感嘆一下,現在什么都要講究包裝,內核里也免不了這個俗,注冊個驅動也要包裝個兩層,不過這個包裝不是為了出名,而是方便大伙兒的。
本來在兩年以前是沒這么多道道兒的,也沒有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/export.h里的定義是
#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函數了
drivers/usb/core/driver.c
int usb_register_driver(struct usb_driver *new_driver, struct module *owner,const char *mod_name)
{int retval = 0;if (usb_disabled())return -ENODEV;new_driver->drvwrap.for_devices = 0;new_driver->drvwrap.driver.name = new_driver->name;new_driver->drvwrap.driver.bus = &usb_bus_type;new_driver->drvwrap.driver.probe = usb_probe_interface;new_driver->drvwrap.driver.remove = usb_unbind_interface;new_driver->drvwrap.driver.owner = owner;new_driver->drvwrap.driver.mod_name = mod_name;spin_lock_init(&new_driver->dynids.lock);INIT_LIST_HEAD(&new_driver->dynids.list);retval = driver_register(&new_driver->drvwrap.driver);if (retval)goto out;retval = usb_create_newid_files(new_driver);if (retval)goto out_newid;pr_info("%s: registered new interface driver %s\n",usbcore_name, new_driver->name);out:return retval;out_newid:driver_unregister(&new_driver->drvwrap.driver);printk(KERN_ERR "%s: error %d registering interface "" driver %s\n",usbcore_name, retval, new_driver->name);goto out;
}這函數和前面見過的usb_register_device_driver長的很相,你如果是從那里一路看過來的話,不用俺說什么,你都會明明白白它的意思。不過,本著與人為善的態度,俺還是要簡單提一點,for_devices在9行設置成了0,有了這行,match里的那個is_usb_device_driver把門兒的才不會把它當成設備驅動放過去。然后就是在19行將你的驅動提交給設備模型,從而添加到usb總線的驅動鏈表里,從此之后,接口和接口驅動就可以通過usb總線的match函數傳情達意眉來眼去。當然,usb的世界里要想對上眼,都得嚴格的滿足對方的條件。
總結
以上是生活随笔為你收集整理的Linux那些事儿 之 戏说USB(34)接口的驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 山药和淮山有什么区别吗?教你4招轻松分辨
- 下一篇: Linux那些事儿 之 戏说USB(大结