參考:
1)《LINUX設(shè)備驅(qū)動(dòng)程序》第十四章 Linux 設(shè)備模型
2)內(nèi)核源碼2.6.38
內(nèi)核初始化的時(shí)候會(huì)對(duì)設(shè)備模型作初始化,見init/main.c: start_kernel->rest_init->kernel_init->do_basic_setup->driver_init
設(shè)備模型中重要的數(shù)據(jù)結(jié)構(gòu):
include/linux/kobject.h:
struct kobject
struct kset
include/linux/device.h:
struct device
struct device_driver
struct bus_type
struct class
1. kobject
Linux設(shè)備驅(qū)動(dòng)模型是一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu),kobject是構(gòu)成設(shè)備驅(qū)動(dòng)模型的基本元素,它總是嵌入到其他結(jié)構(gòu)中,用于把高級(jí)對(duì)象連接到設(shè)備驅(qū)動(dòng)模型上。kobject類似于面向?qū)ο笾械幕悾琩evice,device driver,bus,class便是它的派生產(chǎn)物。struct device,struct device_driver,struct bus_type,struct class中都包含一個(gè)類型為struct kobject的成員。
kobject和虛擬文件系統(tǒng)sysfs有著緊密的聯(lián)系,一個(gè)kobject結(jié)構(gòu)對(duì)應(yīng)sysfs下的一個(gè)目錄。
Documentation/kobject.txt和Documentation/filesystems/sysfs.txt對(duì)kobject和sysfs有詳細(xì)描述。
struct kobject定義在include/linux/kobject.h中:
60 struct kobject { 61 const char *name; /*對(duì)應(yīng)sysfs中的目錄名*/ 62 struct list_head entry; /*同類kobject組成一個(gè)雙向鏈表,entry是該鏈表中的一個(gè)節(jié)點(diǎn)*/ 63 struct kobject *parent; /*指向父kobject*/ 64 struct kset *kset; /*指向所屬的kset*/ 65 struct kobj_type *ktype; /*struct kobj_type中的struct attribute對(duì)應(yīng)sysfs中的文件*/ 66 struct sysfs_dirent *sd; 67 struct kref kref; 68 unsigned int state_initialized:1; 69 unsigned int state_in_sysfs:1; 70 unsigned int state_add_uevent_sent:1; 71 unsigned int state_remove_uevent_sent:1; 72 unsigned int uevent_supPRess:1; 73 };內(nèi)核用kobject結(jié)構(gòu)將各個(gè)對(duì)象連接起來組成一個(gè)分層的結(jié)構(gòu)體系,有兩種獨(dú)立的機(jī)制用于連接:parent指針和kset。
在kobject結(jié)構(gòu)中的parent成員指向另一個(gè)kobject結(jié)構(gòu),這個(gè)結(jié)構(gòu)表示了分層結(jié)構(gòu)中的上一層節(jié)點(diǎn)。父kobject和kobject在sysfs中表現(xiàn)為目錄與子目錄的關(guān)系。
kset是同類kobject的集合。
struct kset定義在include/linux/kobject.h中:
159 struct kset { 160 struct list_head list; /*kset包含的kobject組成一個(gè)鏈表,list指向該鏈表頭*/161 spinlock_t list_lock; 162 struct kobject kobj; 163 const struct kset_uevent_ops *uevent_ops; 164 };kset通過鏈表來管理集合中的kobject,struct kset中的list成員指向該鏈表頭。
struct kset結(jié)構(gòu)中亦有一個(gè)struct kobject類型的成員,故kset在sysfs中同樣對(duì)應(yīng)一個(gè)目錄。
大部分情況下,kset集合中koject的父kobject都指向該kset中的kobject成員。
kset,parent,kobject的關(guān)系如下圖:

對(duì)kobject的操作函數(shù)定義在lib/kobject.c中。
2. 總線、設(shè)備、驅(qū)動(dòng)、類
下面主要描述一下總線、設(shè)備、驅(qū)動(dòng)、類之間的關(guān)系,Documentation/driver-model下亦有描述。對(duì)于總線、設(shè)備、驅(qū)動(dòng)、類的操作函數(shù)的實(shí)現(xiàn),code shows you everything,詳見drivers/base下的bus.c,core.c,driver.c,dd.c,class.c等。
2.1 總線
總線是處理器與一個(gè)或多個(gè)設(shè)備之間的通道,在設(shè)備模型中,所有的設(shè)備都通過總線相連。總線用struct bus_type來描述,bus_type是該總線下設(shè)備和驅(qū)動(dòng)的管理機(jī)構(gòu)。
struct bus_type定義在include/linux/device.h中:
50 struct bus_type { 51 const char *name; 52 struct bus_attribute *bus_attrs; 53 struct device_attribute *dev_attrs; 54 struct driver_attribute *drv_attrs; 55 56 int (*match)(struct device *dev, struct device_driver *drv); 57 int (*uevent)(struct device *dev, struct kobj_uevent_env *env); 58 int (*probe)(struct device *dev); 59 int (*remove)(struct device *dev); 60 void (*shutdown)(struct device *dev); 61 62 int (*suspend)(struct device *dev, pm_message_t state); 63 int (*resume)(struct device *dev); 64 65 const struct dev_pm_ops *pm; 66 67 struct subsys_private *p; 68 }; 重點(diǎn)看一下結(jié)構(gòu)struct subsys_private,該結(jié)構(gòu)描述了總線與設(shè)備和驅(qū)動(dòng)的關(guān)系:
27 struct subsys_private { 28 struct kset subsys; 29 struct kset *devices_kset; 30 31 struct kset *drivers_kset; 32 struct klist klist_devices; 33 struct klist klist_drivers; 34 struct blocking_notifier_head bus_notifier; 35 unsigned int drivers_autoprobe:1; 36 struct bus_type *bus; 37 38 struct list_head class_interfaces; 39 struct kset glue_dirs; 40 struct mutex class_mutex; 41 struct class *class; 42 };1)devices_kset和drivers_kset分別指向該總線下所有設(shè)備和驅(qū)動(dòng)的集合,在sysfs中,/sys/bus/xxx/下總是存在/sys/bus/xxx/devices和/sys/bus/xxx/drivers目錄。
2)bus_type還管理著兩個(gè)鏈表,klist_devices和 klist_drivers,分別表示該總線下的所有設(shè)備和所有驅(qū)動(dòng)。
2.2 設(shè)備
設(shè)備驅(qū)動(dòng)模型中,每一個(gè)設(shè)備都用struct device描述,struct device定義在include/linux/device.h中,下面只列出部分成員:
struct device { 407 struct device *parent; 408 409 struct device_private *p; 410 411 struct kobject kobj; ...... ......418 419 struct bus_type *bus; /* type of bus device is on */ 420 struct device_driver *driver; /* which driver has allocated this 421 device */ ...... ......452 453 struct klist_node knode_class; 454 struct class *class; ...... ......458 }; 68 struct device_private { 69 struct klist klist_children; 70 struct klist_node knode_parent; 71 struct klist_node knode_driver; 72 struct klist_node knode_bus; 73 void *driver_data; 74 struct device *device; 75 };1)父子關(guān)系:它是一個(gè)父設(shè)備,它維護(hù)一個(gè)子設(shè)備的鏈表klist_children;它同時(shí)是一個(gè)子設(shè)備, parent指向它的父設(shè)備,knode_parent是該設(shè)備在其父設(shè)備的子設(shè)備鏈表中的節(jié)點(diǎn);
2)與總線的關(guān)系:它掛在某個(gè)總線下,bus指向該總線的bus_type結(jié)構(gòu), knode_bus是其所在總線所維護(hù)的設(shè)備鏈表中的一個(gè)節(jié)點(diǎn);
3)與驅(qū)動(dòng)的關(guān)系:它是一個(gè)設(shè)備,理所當(dāng)然要跟一個(gè)驅(qū)動(dòng)匹配, driver指向與該設(shè)備匹配的device_driver結(jié)構(gòu),bus下的每一個(gè)驅(qū)動(dòng)會(huì)維護(hù)一個(gè)設(shè)備鏈表表示該驅(qū)動(dòng)支持的所有設(shè)備, knode_driver便表示該鏈表下的一個(gè)節(jié)點(diǎn);
4)與類的關(guān)系:類是一個(gè)設(shè)備的高層視圖,它抽象出了底層的實(shí)現(xiàn)細(xì)節(jié),允許用戶空間使用設(shè)備所提供的功能,而不關(guān)心設(shè)備是如何連接以及它們是如何工作的。即具體相似功能的設(shè)備被劃為一類。class 指向該設(shè)備所屬的類,每個(gè)類會(huì)維護(hù)一個(gè)鏈表表示該類型下的所有設(shè)備, knode_class便是該鏈表中的一個(gè)節(jié)點(diǎn)。
2.3 驅(qū)動(dòng)
struct device_driver用來描述驅(qū)動(dòng)程序,其定義在include/linux下:
122 struct device_driver { 123 const char *name; 124 struct bus_type *bus; 125 ...... ......144 struct driver_private *p; 145 }; 45 struct driver_private { 46 struct kobject kobj; 47 struct klist klist_devices; 48 struct klist_node knode_bus; 49 struct module_kobject *mkobj; 50 struct device_driver *driver; 51 };1)與設(shè)備的關(guān)系:每個(gè)驅(qū)動(dòng)程序可以支持多個(gè)設(shè)備,device_driver維護(hù)了一個(gè)鏈表表示該驅(qū)動(dòng)支持的所有設(shè)備,klist_devices指向該鏈表頭;
2)與總線的關(guān)系:每個(gè)總線維護(hù)一個(gè)鏈表表示該總線下的所有驅(qū)動(dòng),knode_bus便是該鏈表下的一個(gè)節(jié)點(diǎn), bus指向該驅(qū)動(dòng)所在的總線;
2.4 類
類是一個(gè)設(shè)備的高層視圖,它抽象出了底層的實(shí)現(xiàn)細(xì)節(jié),允許用戶空間使用設(shè)備所提供的功能,而不關(guān)心設(shè)備是如何連接以及它們是如何工作的。即具體相似功能的設(shè)備被劃為一類。類用struct class描述,定義在include/device.h中:
193 struct class { 194 const char *name; 195 struct module *owner; 196 197 struct class_attribute *class_attrs; 198 struct device_attribute *dev_attrs; 199 struct bin_attribute *dev_bin_attrs; 200 struct kobject *dev_kobj; 201 202 int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); 203 char *(*devnode)(struct device *dev, mode_t *mode); 204 205 void (*class_release)(struct class *class); 206 void (*dev_release)(struct device *dev); 207 208 int (*suspend)(struct device *dev, pm_message_t state); 209 int (*resume)(struct device *dev); 210 211 const struct kobj_ns_type_Operations *ns_type; 212 const void *(*namespace)(struct device *dev); 213 214 const struct dev_pm_ops *pm; 215 216 struct subsys_private *p; 217 }; 27 struct subsys_private { 28 struct kset subsys; 29 struct kset *devices_kset; 30 31 struct kset *drivers_kset; 32 struct klist klist_devices; 33 struct klist klist_drivers; 34 struct blocking_notifier_head bus_notifier; 35 unsigned int drivers_autoprobe:1; 36 struct bus_type *bus; 37 38 struct list_head class_interfaces; 39 struct kset glue_dirs; 40 struct mutex class_mutex; 41 struct class *class; 42 };1)與設(shè)備的關(guān)系:每個(gè)類會(huì)維護(hù)一個(gè)鏈表表示該類型下的所有設(shè)備, devices_kset指向該鏈表頭
新聞熱點(diǎn)
疑難解答
圖片精選