【设备驱动模型】
设备驱动模型提供了硬件的抽象:使用该抽象完成很多硬件重复的工作,如电源管理、即插即用设备支持、与用户空间的通信等。
sysfs文件系统:Linux设备驱动模型由大量的数据结构和算法构成,非常复杂,因此引入sysfs文件系统来显示设备驱动模型的复杂关系。sysfs是一个只存在于内存中的文件系统。内核通过这个文件系统将设备信息导出到用户空间。sysfs文件系统是内核对象(kobject)、属性(kobj_type)及他们之间的相互关系的一种表现机制。用户可以从sysfs文件系统中读出内核数据,也可以将用户空间的数据写入内核中,从而设置驱动程序的属性和状态。
Linux 内核结构 和 sysfs文件系统 的对应关系:
Linux内核中的结构 sysfs中的结构
kobject <-----------------------------------> 目录
kobj_type <----------------------------------> 属性文件
对象之间的关系<--------------------------> 符号链接
在sysfs文件系统中,设备使用树形目录来表示,树形目录中的每个目录都对应于内核中的一个kobject对象。
59 struct kobject {
60 const char *name;
61 struct list_head entry;
62 struct kobject *parent;
63 struct kset *kset;
64 struct kobj_type *ktype;
65 struct sysfs_dirent *sd;
66 struct kref kref;
67 unsigned int state_initialized:1;
68 unsigned int state_in_sysfs:1;
69 unsigned int state_add_uevent_sent:1;
70 unsigned int state_remove_uevent_sent:1;
71 unsigned int uevent_suppress:1;
72 };
每个kobject对象都有一些属性,这些属性有kobj_type结构体表示。
107 struct kobj_type {
108 void (*release)(struct kobject *kobj);
109 struct sysfs_ops *sysfs_ops;
110 struct attribute **default_attrs;
111 };
kobject和kobj_type之间的关系如图所示:
kobject始终代表sysfs文件系统中的一个目录,kobject对象的成员name是sysfs文件系统中的目录名。
kobject在sysfs文件系统中的位置由parent指针指定。
kobj_type是kobject的属性。attribute结构体表示一个属性。sysfs_ops表示对属性的操作函数。
28 struct attribute {
29 const char *name;
30 struct module *owner;
31 mode_t mode;
32 };
77 struct sysfs_ops {
78 ssize_t (*show)(struct kobject *, struct attribute *,char *);
79 ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
80 };
在编写设备驱动时,一般把kobject包含在一个更大的自定义结构体中。
另外,kobject可以通过kset组织成层次化的结构,kset是具有相同类型的kobject的集合,这也说明kset本身也对应一个目录。
154 struct kset {
155 struct list_head list;
156 spinlock_t list_lock;
157 struct kobject kobj;
158 struct kset_uevent_ops *uevent_ops;
159 };
kset与kobject的关系如图所示:
/********************************************************************************///
设备驱动模型由三大组件构成:总线、设备、驱动。
其中总线是一个抽象的总线,所有的设备和驱动都会挂接到一个总线上。然后设备需要和对应的驱动程序绑定后才能使用。
1. 总线用bus_type表示:
51 struct bus_type {
52 const char *name;
53 struct bus_attribute *bus_attrs;
54 struct device_attribute *dev_attrs;
55 struct driver_attribute *drv_attrs;
56
57 int (*match)(struct device *dev, struct device_driver *drv);
58 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
59 int (*probe)(struct device *dev);
60 int (*remove)(struct device *dev);
61 void (*shutdown)(struct device *dev);
62
63 int (*suspend)(struct device *dev, pm_message_t state);
64 int (*resume)(struct device *dev);
65
66 const struct dev_pm_ops *pm;
67
68 struct bus_type_private *p;
69 };
其中总线属性bus_attrs、设备属性dev_attrs、驱动属性drv_attrs,与kobject对应的属性类似。
38 struct bus_attribute {
39 struct attribute attr;
40 ssize_t (*show)(struct bus_type *bus, char *buf);
41 ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
42 };
在bus_type结构体中定义了许多方法。当一条总线上的新设备或者新驱动被添加时,会一次或多次调用match()函数。当用户空间产生热插拔事件前,可能需要内核传递一些参数给用户程序,这只能使用环境变量来传递参数,传递环境变量的函数由uevent()实现。
bus_type_private是总线私有数据结构,主要包括了3个成员:代表该bus的subsys、挂接到该bus上的驱动集合drivers_kset、挂接到该bus上的设备集合devices_kset。
19 struct bus_type_private {
20 struct kset subsys;
21 struct kset *drivers_kset;
22 struct kset *devices_kset;
23 struct klist klist_devices;
24 struct klist klist_drivers;
25 struct blocking_notifier_head bus_notifier;
26 unsigned int drivers_autoprobe:1;
27 struct bus_type *bus;
28 };
如果为驱动程序定义了一条新的总线,则需要调用bus_register()函数进行注册,当从系统中删除一条总线时,则需要调用bus_unregister()函数进行删除。
2. 设备用device结构体表示:
379 struct device {
380 struct device *parent;
381
382 struct device_private *p;
383
384 struct kobject kobj;
385 const char *init_name; /* initial name of the device */
386 struct device_type *type;
387
388 struct semaphore sem; /* semaphore to synchronize calls to
389 * its driver.
390 */
391
392 struct bus_type *bus; /* type of bus device is on */
393 struct device_driver *driver; /* which driver has allocated this
394 device */
395 void *platform_data; /* Platform specific data, device
396 core doesn't touch it */
397 struct dev_pm_info power;
398
399 #ifdef CONFIG_NUMA
400 int numa_node; /* NUMA node this device is close to */
401 #endif
402 u64 *dma_mask; /* dma mask (if dma'able device) */
403 u64 coherent_dma_mask;/* Like dma_mask, but for
404 alloc_coherent mappings as
405 not all hardware supports
406 64 bit addresses for consistent
407 allocations such descriptors. */
408
409 struct device_dma_parameters *dma_parms;
410
411 struct list_head dma_pools; /* dma pools (if dma'ble) */
412
413 struct dma_coherent_mem *dma_mem; /* internal for coherent mem
414 override */
415 /* arch specific additions */
416 struct dev_archdata archdata;
417
418 dev_t devt; /* dev_t, creates the sysfs "dev" */
419
420 spinlock_t devres_lock;
421 struct list_head devres_head;
422
423 struct klist_node knode_class;
424 struct class *class;
425 const struct attribute_group **groups; /* optional groups */
426
427 void (*release)(struct device *dev);
428 };
同理有设备注册和注销,还有设备属性。
3. 驱动用device_driver结构体表示:
122 struct device_driver {
123 const char *name;
124 struct bus_type *bus;
125
126 struct module *owner;
127 const char *mod_name; /* used for built-in modules */
128
129 bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
130
131 int (*probe) (struct device *dev);
132 int (*remove) (struct device *dev);
133 void (*shutdown) (struct device *dev);
134 int (*suspend) (struct device *dev, pm_message_t state);
135 int (*resume) (struct device *dev);
136 const struct attribute_group **groups;
137
138 const struct dev_pm_ops *pm;
139
140 struct driver_private *p;
141 };
同理有驱动程序的注册和注销,还有驱动的属性。