Linux那些事儿 之 戏说USB(34)接口的驱动
生活随笔
收集整理的這篇文章主要介紹了
Linux那些事儿 之 戏说USB(34)接口的驱动
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
從上節(jié)的上節(jié)我們已經(jīng)知道,usb_generic_driver在自己的生命線里,以一己之力將設(shè)備的各個(gè)接口送給了linux的設(shè)備模型,讓usb總線的match函數(shù),也就是usb_device_match,在自己的那條驅(qū)動(dòng)鏈表里為它們尋找一個(gè)合適的接口驅(qū)動(dòng)程序?,F(xiàn)在讓咱們輕聲的問一句,這些接口驅(qū)動(dòng)都從哪里來?
這就要說到每個(gè)玩兒linux的人都會(huì)知道的那幾個(gè)著名的命令insmod,modprobe,rmmod。你insmod或modprobe驅(qū)動(dòng)的時(shí)候,經(jīng)過一個(gè)曲折的過程,會(huì)調(diào)用到你驅(qū)動(dòng)里的那個(gè)xxx_init函數(shù),進(jìn)而去調(diào)用usb_register()將你的驅(qū)動(dòng)提交給設(shè)備模型,添加到usb總線的驅(qū)動(dòng)鏈表里。你rmmod驅(qū)動(dòng)時(shí)候,同樣經(jīng)過一個(gè)曲折的過程之后,調(diào)用到你驅(qū)動(dòng)里的那個(gè)xxx_cleanup函數(shù),進(jìn)而調(diào)用usb_deregister()將你的驅(qū)動(dòng)從usb總線的驅(qū)動(dòng)鏈表里刪除掉?,F(xiàn)在就看看include/linux/usb.h里定義的usb_register函數(shù)
本來在兩年以前是沒這么多道道兒的,也沒有usb_register_driver這么一個(gè)函數(shù),只有個(gè)usb_register(),它直接就把啥事兒都做了。而且那個(gè)時(shí)候struct usb_driver結(jié)構(gòu)里還有一個(gè)有名的owner字段,每個(gè)在那個(gè)歲月里寫過usb驅(qū)動(dòng)的人都會(huì)認(rèn)得它,并且都會(huì)毫無猶豫的將它設(shè)置為THIS_MODULE。但是經(jīng)過歲月的洗禮,在早先貼出來的struct usb_driver結(jié)構(gòu)內(nèi)容里,你發(fā)現(xiàn)owner已經(jīng)無影無蹤了。要搞清楚這個(gè)歷史變遷的來龍去脈,你得知道這個(gè)owner和THIS_MODULE都代表了什么。
從那個(gè)時(shí)代走過來的人,都應(yīng)該知道owner是一個(gè)struct module *類型的結(jié)構(gòu)體指針,現(xiàn)在告訴你的是每個(gè)struct module結(jié)構(gòu)體在內(nèi)核里都代表了一個(gè)內(nèi)核模塊,就像十七大里的每個(gè)代表都代表了一批人,至于代表了什么人,選他們的人才知道,同樣,每個(gè)struct module結(jié)構(gòu)體代表了什么模塊,對(duì)它進(jìn)行初始化的模塊才知道。當(dāng)然,初始化這個(gè)結(jié)構(gòu)不是寫驅(qū)動(dòng)的人該做的事,是在剛才略過的那個(gè)從insmod或modprobe到你驅(qū)動(dòng)的xxx_init函數(shù)的曲折過程中做的事。insmod命令執(zhí)行后,會(huì)調(diào)用kernel/module.c里的一個(gè)系統(tǒng)調(diào)用sys_init_module,它會(huì)調(diào)用load_module函數(shù),將用戶空間傳入的整個(gè)內(nèi)核模塊文件創(chuàng)建成一個(gè)內(nèi)核模塊,并返回一個(gè)struct module結(jié)構(gòu)體,從此,內(nèi)核中便以這個(gè)結(jié)構(gòu)體代表這個(gè)內(nèi)核模塊。
再看看THIS_MODULE宏是什么意思,它在include/linux/export.h里的定義是
這就要說到每個(gè)玩兒linux的人都會(huì)知道的那幾個(gè)著名的命令insmod,modprobe,rmmod。你insmod或modprobe驅(qū)動(dòng)的時(shí)候,經(jīng)過一個(gè)曲折的過程,會(huì)調(diào)用到你驅(qū)動(dòng)里的那個(gè)xxx_init函數(shù),進(jìn)而去調(diào)用usb_register()將你的驅(qū)動(dòng)提交給設(shè)備模型,添加到usb總線的驅(qū)動(dòng)鏈表里。你rmmod驅(qū)動(dòng)時(shí)候,同樣經(jīng)過一個(gè)曲折的過程之后,調(diào)用到你驅(qū)動(dòng)里的那個(gè)xxx_cleanup函數(shù),進(jìn)而調(diào)用usb_deregister()將你的驅(qū)動(dòng)從usb總線的驅(qū)動(dòng)鏈表里刪除掉?,F(xiàn)在就看看include/linux/usb.h里定義的usb_register函數(shù)
#define usb_register(driver) \usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)看到這個(gè)函數(shù),讓人不得不感嘆一下,現(xiàn)在什么都要講究包裝,內(nèi)核里也免不了這個(gè)俗,注冊(cè)個(gè)驅(qū)動(dòng)也要包裝個(gè)兩層,不過這個(gè)包裝不是為了出名,而是方便大伙兒的。
本來在兩年以前是沒這么多道道兒的,也沒有usb_register_driver這么一個(gè)函數(shù),只有個(gè)usb_register(),它直接就把啥事兒都做了。而且那個(gè)時(shí)候struct usb_driver結(jié)構(gòu)里還有一個(gè)有名的owner字段,每個(gè)在那個(gè)歲月里寫過usb驅(qū)動(dòng)的人都會(huì)認(rèn)得它,并且都會(huì)毫無猶豫的將它設(shè)置為THIS_MODULE。但是經(jīng)過歲月的洗禮,在早先貼出來的struct usb_driver結(jié)構(gòu)內(nèi)容里,你發(fā)現(xiàn)owner已經(jīng)無影無蹤了。要搞清楚這個(gè)歷史變遷的來龍去脈,你得知道這個(gè)owner和THIS_MODULE都代表了什么。
從那個(gè)時(shí)代走過來的人,都應(yīng)該知道owner是一個(gè)struct module *類型的結(jié)構(gòu)體指針,現(xiàn)在告訴你的是每個(gè)struct module結(jié)構(gòu)體在內(nèi)核里都代表了一個(gè)內(nèi)核模塊,就像十七大里的每個(gè)代表都代表了一批人,至于代表了什么人,選他們的人才知道,同樣,每個(gè)struct module結(jié)構(gòu)體代表了什么模塊,對(duì)它進(jìn)行初始化的模塊才知道。當(dāng)然,初始化這個(gè)結(jié)構(gòu)不是寫驅(qū)動(dòng)的人該做的事,是在剛才略過的那個(gè)從insmod或modprobe到你驅(qū)動(dòng)的xxx_init函數(shù)的曲折過程中做的事。insmod命令執(zhí)行后,會(huì)調(diào)用kernel/module.c里的一個(gè)系統(tǒng)調(diào)用sys_init_module,它會(huì)調(diào)用load_module函數(shù),將用戶空間傳入的整個(gè)內(nèi)核模塊文件創(chuàng)建成一個(gè)內(nèi)核模塊,并返回一個(gè)struct module結(jié)構(gòu)體,從此,內(nèi)核中便以這個(gè)結(jié)構(gòu)體代表這個(gè)內(nèi)核模塊。
再看看THIS_MODULE宏是什么意思,它在include/linux/export.h里的定義是
#define THIS_MODULE (&__this_module)是一個(gè)struct module變量,代表當(dāng)前模塊,與那個(gè)著名的current有幾分相似,可以通過THIS_MODULE宏來引用模塊的struct module結(jié)構(gòu),比如使用THIS_MODULE->state可以獲得當(dāng)前模塊的狀態(tài)?,F(xiàn)在你應(yīng)該明白為啥在那個(gè)歲月里,你需要毫不猶豫毫不遲疑的將struct usb_driver結(jié)構(gòu)里的owner設(shè)置為THIS_MODULE了吧,這個(gè)owner指針指向的就是你的模塊自己。那現(xiàn)在owner咋就說沒就沒了那?這個(gè)說來可就話長(zhǎng)了,咱就長(zhǎng)話短說吧。不知道那個(gè)時(shí)候你有沒有忘記過初始化owner,反正是很多人都會(huì)忘記,大家都把注意力集中到probe、disconnect等等需要?jiǎng)幽X子的角色上面了,這個(gè)不需要?jiǎng)幽X子,只需要花個(gè)幾秒鐘指定一下的owner反倒常常被忽視。于是在2006年的春節(jié)前夕,在咱們都無心工作無心學(xué)習(xí)等著過春節(jié)的時(shí)候,Greg堅(jiān)守一線,去掉了owner,于是千千萬萬個(gè)寫usb驅(qū)動(dòng)的人再也不用去時(shí)刻謹(jǐn)記初始化owner了。咱們是不用設(shè)置owner了,可core里不能不設(shè)置,struct usb_driver結(jié)構(gòu)里不是沒有owner了么,可它里面嵌的那個(gè)struct device_driver結(jié)構(gòu)里還有啊,設(shè)置了它就可以了。于是Greg同時(shí)又增加了usb_register_driver()這么一層,usb_register()可以通過將參數(shù)指定為THIS_MODULE去調(diào)用它,所有的事情都挪到它里面去做。反正usb_register()也是宏定義,并不會(huì)增加調(diào)用的開銷?,F(xiàn)在是時(shí)機(jī)看看usb_register_driver函數(shù)了
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;
}這函數(shù)和前面見過的usb_register_device_driver長(zhǎng)的很相,你如果是從那里一路看過來的話,不用俺說什么,你都會(huì)明明白白它的意思。不過,本著與人為善的態(tài)度,俺還是要簡(jiǎn)單提一點(diǎn),for_devices在9行設(shè)置成了0,有了這行,match里的那個(gè)is_usb_device_driver把門兒的才不會(huì)把它當(dāng)成設(shè)備驅(qū)動(dòng)放過去。然后就是在19行將你的驅(qū)動(dòng)提交給設(shè)備模型,從而添加到usb總線的驅(qū)動(dòng)鏈表里,從此之后,接口和接口驅(qū)動(dòng)就可以通過usb總線的match函數(shù)傳情達(dá)意眉來眼去。當(dāng)然,usb的世界里要想對(duì)上眼,都得嚴(yán)格的滿足對(duì)方的條件。
總結(jié)
以上是生活随笔為你收集整理的Linux那些事儿 之 戏说USB(34)接口的驱动的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 山药和淮山有什么区别吗?教你4招轻松分辨
- 下一篇: 长期吸烟却又喜欢喝茶的人,后来怎么样了?