參考:
1)《LINUX裝置驅動程式》第十四章 Linux 裝置模型
2)核心源碼2.6.38
核心初始化的時候會對裝置模型作初始化,見init/main.c: start_kernel->rest_init->kernel_init->do_basic_setup->driver_init
裝置模型中重要的資料結構:
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裝置驅動模型是一個複雜的資料結構,kobject是構成裝置驅動模型的基本元素,它總是嵌入到其他結構中,用於把進階對象串連到裝置驅動模型上。kobject類似於物件導向中的基類,device,device driver,bus,class便是它的派生產物。struct device,struct device_driver,struct bus_type,struct class中都包含一個類型為struct kobject的成員。
kobject和虛擬檔案系統sysfs有著緊密的聯絡,一個kobject結構對應sysfs下的一個目錄。
Documentation/kobject.txt和Documentation/filesystems/sysfs.txt對kobject和sysfs有詳細描述。
struct kobject定義在include/linux/kobject.h中:
60 struct kobject {
61 const char *name; /*對應sysfs中的目錄名*/ 62 struct list_head entry; /*同類kobject組成一個雙向鏈表,entry是該鏈表中的一個節點*/ 63 struct kobject *parent; /*指向父kobject*/ 64 struct kset *kset; /*指向所屬的kset*/ 65 struct kobj_type *ktype; /*struct kobj_type中的struct attribute對應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 };
核心用kobject結構將各個對象串連起來組成一個分層的結構體系,有兩種獨立的機制用於串連:parent指標和kset。
在kobject結構中的parent成員指向另一個kobject結構,這個結構表示了分層結構中的上一層節點。父kobject和kobject在sysfs中表現為目錄與子目錄的關係。
kset是同類kobject的集合。
struct kset定義在include/linux/kobject.h中:
159 struct kset { 160 struct list_head list; /*kset包含的kobject組成一個鏈表,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結構中亦有一個struct kobject類型的成員,故kset在sysfs中同樣對應一個目錄。
大部分情況下,kset集合中koject的父kobject都指向該kset中的kobject成員。
kset,parent,kobject的關係如:
對kobject的操作函數定義在lib/kobject.c中。
2. 匯流排、裝置、驅動、類
下面主要描述一下匯流排、裝置、驅動、類之間的關係,Documentation/driver-model下亦有描述。對於匯流排、裝置、驅動、類的操作函數的實現,code shows you everything,詳見drivers/base下的bus.c,core.c,driver.c,dd.c,class.c等。
2.1 匯流排
匯流排是處理器與一個或多個裝置之間的通道,在裝置模型中,所有的裝置都通過匯流排相連。匯流排用struct bus_type來描述,bus_type是該匯流排下裝置和驅動的管理機構。
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 };
重點看一下結構struct subsys_private,該結構描述了匯流排與裝置和驅動的關係:
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分別指向該匯流排下所有裝置和驅動的集合,在sysfs中,/sys/bus/xxx/下總是存在/sys/bus/xxx/devices和/sys/bus/xxx/drivers目錄。
2)bus_type還管理著兩個鏈表,klist_devices和 klist_drivers,分別表示該匯流排下的所有裝置和所有驅動。
2.2 裝置
裝置驅動模型中,每一個裝置都用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)父子關係:它是一個父裝置,它維護一個子裝置的鏈表klist_children;它同時是一個子裝置, parent指向它的父裝置,knode_parent是該裝置在其父裝置的子裝置鏈表中的節點;
2)與匯流排的關係:它掛在某個匯流排下,bus指向該匯流排的bus_type結構, knode_bus是其所在匯流排所維護的裝置鏈表中的一個節點;
3)與驅動的關係:它是一個裝置,理所當然要跟一個驅動匹配, driver指向與該裝置匹配的device_driver結構,bus下的每一個驅動會維護一個裝置鏈表表示該驅動支援的所有裝置, knode_driver便表示該鏈表下的一個節點;
4)與類的關係:類是一個裝置的高層視圖,它抽象出了底層的實現細節,允許使用者空間使用裝置所提供的功能,而不關心裝置是如何串連以及它們是如何工作的。即具體相似功能的裝置被劃為一類。class 指向該裝置所屬的類,每個類會維護一個鏈表表示該類型下的所有裝置, knode_class便是該鏈表中的一個節點。
2.3 驅動
struct device_driver用來描述驅動程式,其定義在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)與裝置的關係:每個驅動程式可以支援多個裝置,device_driver維護了一個鏈表表示該驅動支援的所有裝置,klist_devices指向該鏈表頭;
2)與匯流排的關係:每個匯流排維護一個鏈表表示該匯流排下的所有驅動,knode_bus便是該鏈表下的一個節點, bus指向該驅動所在的匯流排;
2.4 類
類是一個裝置的高層視圖,它抽象出了底層的實現細節,允許使用者空間使用裝置所提供的功能,而不關心裝置是如何串連以及它們是如何工作的。即具體相似功能的裝置被劃為一類。類用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)與裝置的關係:每個類會維護一個鏈表表示該類型下的所有裝置, devices_kset指向該鏈表頭