1. 程式人生 > >Linux內核(8) - 設備模型(下)

Linux內核(8) - 設備模型(下)

chm 什麽 gist attach log 準備 http 是否 成了

設備模型拍得再玄幻,它也只是個模型,必須得落實在具體的子系統,否則就只能抱著個最佳技術獎空遺恨。既然前面已經以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所提供的默默無聞又不可或缺的支持。

Linux內核(8) - 設備模型(下)