《Linux內核修煉之道》精華分享與討論(12)——設備模型(下)

推薦博文: Linux內核“問題門”——學習問題、經驗集錦

推薦下載:《Linux內核修煉之道》精華版之方法論

設備模型拍得再玄幻,它也只是個模型,必須得落實在具體的子系統,否則就只能抱着個最佳技術獎空遺恨。既然前面已經以USB子系統的實現分析示例了分析內核源碼應該如何入手,那麼這裏就仍然以USB子系統爲例,看看設備模型是如何軟着陸的。

內核中USB子系統的結構

我們已經知道了USB子系統的代碼都位於drivers/usb目錄下面,也認識了一個很重要的目錄——core子目錄。現在,我們再來看一個很重要的模塊——usbcore。你可以使用“lsmod”命令看一下,在顯示的結果裏能夠找到有一個模塊叫做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設備,那麼兩個模塊是必須的:一個是usbcore,這就是核心模塊;另一個是主機控制器的驅動程序,比如這裏usbcore那一行我們看到的ehci_hcd和uhci_hcd,你的USB設備要工作,合適的USB主機控制器模塊也是必不可少的。

usbcore負責實現一些核心的功能,爲別的設備驅動程序提供服務,提供一個用於訪問和控制USB硬件的接口,而不用去考慮系統當前存在哪種主機控制器。至於core、主機控制器和USB驅動三者之間的關係,如下圖所示。
 
USB驅動和主機控制器就像core的兩個保鏢,協議裏也說了,主機控制器的驅動(HCD)必須位於USB軟件的最下一層。HCD提供主機控制器硬件的抽象,隱藏硬件的細節,在主機控制器之下是物理的USB及所有與之連接的USB設備。而HCD只有一個客戶,對一個人負責,就是usbcore。usbcore將用戶的請求映射到相關的HCD,用戶不能直接訪問HCD。

core爲咱們完成了大部分的工作,因此咱們寫USB驅動的時候,只能調用core的接口,core會將咱們的請求發送給相應的HCD。

USB子系統與設備模型

關於設備模型,最主要的問題就是,bus、device、driver是如何建立聯繫的?換言之,這三個數據結構中的指針是如何被賦值的?絕對不可能發生的事情是,一旦爲一條總線申請了一個struct bus_type的數據結構之後,它就知道它的devices鏈表和drivers鏈表會包含哪些東西,這些東西一定不會是先天就有的,只能是後天填進來的。

具體到USB子系統,完成這個工作的就是USB core。USB core的代碼會進行整個USB系統的初始化,比如申請struct bus_type usb_bus_type,然後會掃描USB總線,看線上連接了哪些USB設備,或者說Root Hub上連了哪些USB設備,比如說連了一個USB鍵盤,那麼就爲它準備一個struct device,根據它的實際情況,爲這個struct device賦值,並插入devices鏈表中來。

又比如Root Hub上連了一個普通的Hub,那麼除了要爲這個Hub本身準備一個struct device以外,還得繼續掃描看這個Hub上是否又連了別的設備,有的話繼續重複之前的事情,這樣一直進行下去,直到完成整個掃描,最終就把usb_bus_type中的devices鏈表給建立了起來。

那麼drivers鏈表呢?這個就不用bus方面主動了,而該由每一個driver本身去bus上面登記,或者說掛牌。具體到USB子系統,每一個USB設備的驅動程序都會對應一個struct usb_driver結構,其中有一個struct device_driver driver成員,USB core爲每一個設備驅動準備了一個函數,讓它把自己的這個struct device_driver driver插入到usb_bus_type中的drivers鏈表中去。而這個函數正是我們此前看到的usb_register。而與之對應的usb_deregister所從事的正是與之相反的工作,把這個結構體從drivers鏈表中刪除。

而struct bus_type結構的match函數在USB子系統裏就是usb_device_match函數,它充當了一個紅娘的角色,在USB總線的USB設備和USB驅動之間牽線搭橋,類似於交大BBS上的鵲橋版,雖然它們上面的條件都琳琅滿目的,但明顯這裏match的條件不是那麼的苛刻,要更爲實際些。

可以說,USB core的確是用心良苦,爲每一個USB設備驅動做足了功課,正因爲如此,作爲一個實際的USB設備驅動,它在初始化階段所要做的事情就很少,很簡單了,直接調用usb_register即可。事實上,沒有人是理所當然應該爲你做什麼的,但USB core這麼做了。所以每一個寫USB設備驅動的人應該銘記,USB設備驅動絕不是一個人在工作,在他身後,是USB core所提供的默默無聞又不可或缺的支持。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章