推薦博文: Linux內(nèi)核“問(wèn)題門”——學(xué)習(xí)問(wèn)題、經(jīng)驗(yàn)集錦
<!--EndFragment-->推薦下載: 《Linux內(nèi)核修煉之道》精華版之方法論
設(shè)備模型拍得再玄幻,它也只是個(gè)模型,必須得落實(shí)在具體的子系統(tǒng),否則就只能抱著個(gè)最佳技術(shù)獎(jiǎng)空遺恨。既然前面已經(jīng)以USB子系統(tǒng)的實(shí)現(xiàn)分析示例了分析內(nèi)核源碼應(yīng)該如何入手,那么這里就仍然以USB子系統(tǒng)為例,看看設(shè)備模型是如何軟著陸的。
內(nèi)核中USB子系統(tǒng)的結(jié)構(gòu)
我們已經(jīng)知道了USB子系統(tǒng)的代碼都位于drivers/usb目錄下面,也認(rèn)識(shí)了一個(gè)很重要的目錄——core子目錄。現(xiàn)在,我們?cè)賮?lái)看一個(gè)很重要的模塊——usbcore。你可以使用“l(fā)smod”命令看一下,在顯示的結(jié)果里能夠找到有一個(gè)模塊叫做usbcore。
localhost:/usr/src/linux-2.6.23/drivers/usb/core # lsmod
Module Size Used by
af_packet 55820 2
raw 89504 0
nfs 230840 2
lockd 87536 2 nfs
nfs_acl 20352 1 nfs
sunrpc 172360 4 nfs,lockd,nfs_acl
ipv6 329728 36
button 24224 0
battery 27272 0
ac 22152 0
apparmor 73760 0
aamatch_pcre 30720 1 apparmor
loop 32784 0
usbhid 60832 0
dm_mod 77232 0
ide_cd 57120 0
hw_random 22440 0
ehci_hcd 47624 0
cdrom 52392 1 ide_cd
uhci_hcd 48544 0
shpchp 61984 0
bnx2 157296 0
usbcore 149288 4 usbhid,ehci_hcd,uhci_hcd
e1000 130872 0
pci_hotplug 44800 1 shpchp
reiserfs 239616 2
edd 26760 0
fan 21896 0
??
找到了usbcore那一行嗎?core就是核心,基本上你要在你的電腦里用USB設(shè)備,那么兩個(gè)模塊是必須的:一個(gè)是usbcore,這就是核心模塊;另一個(gè)是主機(jī)控制器的驅(qū)動(dòng)程序,比如這里usbcore那一行我們看到的ehci_hcd和uhci_hcd,你的USB設(shè)備要工作,合適的USB主機(jī)控制器模塊也是必不可少的。
usbcore負(fù)責(zé)實(shí)現(xiàn)一些核心的功能,為別的設(shè)備驅(qū)動(dòng)程序提供服務(wù),提供一個(gè)用于訪問(wèn)和控制USB硬件的接口,而不用去考慮系統(tǒng)當(dāng)前存在哪種主機(jī)控制器。至于core、主機(jī)控制器和USB驅(qū)動(dòng)三者之間的關(guān)系,如下圖所示。
USB驅(qū)動(dòng)和主機(jī)控制器就像core的兩個(gè)保鏢,協(xié)議里也說(shuō)了,主機(jī)控制器的驅(qū)動(dòng)(HCD)必須位于USB軟件的最下一層。HCD提供主機(jī)控制器硬件的抽象,隱藏硬件的細(xì)節(jié),在主機(jī)控制器之下是物理的USB及所有與之連接的USB設(shè)備。而HCD只有一個(gè)客戶,對(duì)一個(gè)人負(fù)責(zé),就是usbcore。usbcore將用戶的請(qǐng)求映射到相關(guān)的HCD,用戶不能直接訪問(wèn)HCD。
core為咱們完成了大部分的工作,因此咱們寫USB驅(qū)動(dòng)的時(shí)候,只能調(diào)用core的接口,core會(huì)將咱們的請(qǐng)求發(fā)送給相應(yīng)的HCD。
USB子系統(tǒng)與設(shè)備模型
關(guān)于設(shè)備模型,最主要的問(wèn)題就是,bus、device、driver是如何建立聯(lián)系的?換言之,這三個(gè)數(shù)據(jù)結(jié)構(gòu)中的指針是如何被賦值的?絕對(duì)不可能發(fā)生的事情是,一旦為一條總線申請(qǐng)了一個(gè)struct bus_type的數(shù)據(jù)結(jié)構(gòu)之后,它就知道它的devices鏈表和drivers鏈表會(huì)包含哪些東西,這些東西一定不會(huì)是先天就有的,只能是后天填進(jìn)來(lái)的。
具體到USB子系統(tǒng),完成這個(gè)工作的就是USB core。USB core的代碼會(huì)進(jìn)行整個(gè)USB系統(tǒng)的初始化,比如申請(qǐng)struct bus_type usb_bus_type,然后會(huì)掃描USB總線,看線上連接了哪些USB設(shè)備,或者說(shuō)Root Hub上連了哪些USB設(shè)備,比如說(shuō)連了一個(gè)USB鍵盤,那么就為它準(zhǔn)備一個(gè)struct device,根據(jù)它的實(shí)際情況,為這個(gè)struct device賦值,并插入devices鏈表中來(lái)。
又比如Root Hub上連了一個(gè)普通的Hub,那么除了要為這個(gè)Hub本身準(zhǔn)備一個(gè)struct device以外,還得繼續(xù)掃描看這個(gè)Hub上是否又連了別的設(shè)備,有的話繼續(xù)重復(fù)之前的事情,這樣一直進(jìn)行下去,直到完成整個(gè)掃描,最終就把usb_bus_type中的devices鏈表給建立了起來(lái)。
那么drivers鏈表呢?這個(gè)就不用bus方面主動(dòng)了,而該由每一個(gè)driver本身去bus上面登記,或者說(shuō)掛牌。具體到USB子系統(tǒng),每一個(gè)USB設(shè)備的驅(qū)動(dòng)程序都會(huì)對(duì)應(yīng)一個(gè)struct usb_driver結(jié)構(gòu),其中有一個(gè)struct device_driver driver成員,USB core為每一個(gè)設(shè)備驅(qū)動(dòng)準(zhǔn)備了一個(gè)函數(shù),讓它把自己的這個(gè)struct device_driver driver插入到usb_bus_type中的drivers鏈表中去。而這個(gè)函數(shù)正是我們此前看到的usb_register。而與之對(duì)應(yīng)的usb_deregister所從事的正是與之相反的工作,把這個(gè)結(jié)構(gòu)體從drivers鏈表中刪除。
而struct bus_type結(jié)構(gòu)的match函數(shù)在USB子系統(tǒng)里就是usb_device_match函數(shù),它充當(dāng)了一個(gè)紅娘的角色,在USB總線的USB設(shè)備和USB驅(qū)動(dòng)之間牽線搭橋,類似于交大BBS上的鵲橋版,雖然它們上面的條件都琳瑯滿目的,但明顯這里match的條件不是那么的苛刻,要更為實(shí)際些。
可以說(shuō),USB core的確是用心良苦,為每一個(gè)USB設(shè)備驅(qū)動(dòng)做足了功課,正因?yàn)槿绱耍鳛橐粋€(gè)實(shí)際的USB設(shè)備驅(qū)動(dòng),它在初始化階段所要做的事情就很少,很簡(jiǎn)單了,直接調(diào)用usb_register即可。事實(shí)上,沒有人是理所當(dāng)然應(yīng)該為你做什么的,但USB core這么做了。所以每一個(gè)寫USB設(shè)備驅(qū)動(dòng)的人應(yīng)該銘記,USB設(shè)備驅(qū)動(dòng)絕不是一個(gè)人在工作,在他身后,是USB core所提供的默默無(wú)聞?dòng)植豢苫蛉钡闹С帧?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
