Linux驱动开发学习归纳-2
【设备驱动模型】
设备驱动模型提供了硬件的抽象:使用该抽象完成很多硬件重复的工作,如电源管理、即插即用设备支持、与用户空间的通信等。
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 };同理有驱动程序的注册和注销,还有驱动的属性。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。