歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

設備模型之總線,驅動,設備基礎教程

Kobject,kset 是設備模型的基本結構體,設備模型使用這兩個結構體來完成設備的層次關系,但在實際的設備驅動編寫中,我們基本上用不到kobject,kset這些結構 體,是因為這些結構體又被嵌入到更大的結構體中,原因在於kobject,kset結構體只能表征設備的層次關系,但是一個設備的驅動,並不是簡單的一個 層次關系而已,因此,必需要把kobject,kset結構體嵌入到更大的結構體中,使用kobject,kset來表征層次關系,用其他的成員表示設備 驅動的具體功能。

在設備模型中,我們將看到,設備驅動主要是由總線,驅動程序,設備三個部分構成,通過這三個標准部件,把各種紛繁雜亂的設備歸結過來,達到簡化設備驅動編寫的目的,也即我們編寫的設備驅動,其實也只是這三部分中的一個很小的部分的。

 

我們編寫的設備驅動程序,一定是先屬於一個總線的驅動,比如屬於 USB總線,或者屬於PCI總線,或者屬於I2C總線,等等,因為我們編寫的設備驅動,在注冊,安裝到系統時,系統會先檢查驅動是屬於哪個總線的(設備驅 動編寫時已經定義好),會把驅動加入到對應的總線的kset中,即把當前設備驅動的kobject加入到對應總線的kset中,形成層次關聯。而當系統檢 測到有設備存在(硬件),也會先判斷設備是屬於哪個總線的(硬件連接),然後遍歷當前總線下的所有設備驅動程序,通過所屬總線的探測函數,查找是否有設備 驅動程序匹配可以驅動當前的設備(一般是通過獲得設備的PID,VID,跟驅動程序的PID,VID比較,看是否匹配而定),如果有驅動程序可以驅動設 備,則把當前設備也加入到所屬總線的kset中,如果沒有可驅動設備的驅動程序,則只能在總線的設備鏈表中存在,而如果設備都無法通過總線的匹配,則也沒 有辦法存在於總線的設備鏈表中。由於一條總線要管理總線上的所有驅動,同時要管理總線上的有所設備,則需要再把所有設備和所有驅動都分開,分別設立一個設 備kset和一個設備驅動kset,用於管理所有的設備和設備驅動,如此,則總線kset實際上包含了兩個kset(設備kset,設備驅動kset), 設備kset又包含了所有的當前總線的設備的kobject,設備驅動kset包含了所有的當前總線的設備驅動的kobject;而所有的總線,又形成了 bus的kset,歸結起來就形成下圖的層次關系:

bus-dirver-device

bus-dirver-device

每個設備,都被掛接到不同的總線上,當設備掛接到對應的總線上 後,其所對應的總線類型就確定了,而設備在掛接到總線上時,總線先要掃描設備,看看設備是否適合總線的要求,如果適合了,那接著就要掃描整個總線上的設備 驅動鏈表,查找是否有驅動程序可以管理設備,如果找到,則把設備結構體中的相應指針成員指向對應的驅動程序,如果暫時沒有找到對應的設備驅動程序,則設備 結構體中的指向驅動程序的指針暫時為空,表示還沒有設備驅動,還在總線的設備隊列中等待;而如果設備不能通過總線的檢查,即不會出現在總線的設備列表上, 自然不會去掃描設備驅動鏈表,查找匹配的驅動了。

而每個設備驅動程序,都是被安裝到對應的總線上的,不論是手動安 裝,還是自動安裝,所謂安裝,就是把驅動程序掛載到對應總線的驅動鏈表中,而掛載到對應的總線驅動鏈表,首先要滿足總線的匹配要求,只有適合了要求,才能 掛載到總線的驅動鏈表,也只有到達這個步驟,系統才會掃描整個總線的設備鏈表,來查找是否有設備需要此驅動來管理,如果找到這個設備,則驅動程序中的設備 管理鏈表,會記錄這個設備的地址,從而達到管理設備的目的。

經過上述的設備插入,或者驅動安裝,系統就會出現只有設備,而沒 有設備驅動程序的情況,也會出現,只有設備驅動程序,沒有對應的設備的情況,此時,設備或者設備驅動程序,就會暫時在各自的隊列裡等待,一旦有驅動程序安 裝,或新的設備插入,就都會自動的去掃描對應的鏈表,來檢測是否有配對的可能。

綜合上述三者的關系,如圖:

bus-dirver-device

bus-dirver-device

Linux設備模型 之 總線類型 - bus_typebus_type

相關數據結構:


struct bus_type {
 char * name;
 struct subsystem subsys;
 struct kset drivers;
 struct kset devices;
 struct bus_attribute * bus_attrs;
 struct device_attribute * dev_attrs;
 struct driver_attribute * drv_attrs;
 int (*match)(struct device * dev, struct device_driver * drv);
 int (*hotplug) (struct device *dev, char **envp,
 int num_envp, char *buffer, int buffer_size);
 int (*suspend)(struct device * dev, pm_message_t state);
 int (*resume)(struct device * dev);
};

內核所支持的每一種總線類型都由一個bus_type對象表示。
bus_type中內嵌了一個subsystem - subsys。
系統中的bus_subsys子系統將所有的bus_type中的subsys集合在一起。
bus_subsys對應sysfs中的/sys/bus目錄.

另外,bus_type中有兩個內嵌的kset對象:devices 和 drivers。分別表示該bus上的設備和驅動。

bus-dirver-device

bus-dirver-device

函數bus_for_each_dev() 和 bus_for_each_drv()分別用於遍歷bus上devices和drivers鏈表中的所有元素。

Copyright © Linux教程網 All Rights Reserved