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之间的关系如图所示:

Linux驱动开发学习归纳-2

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的关系如图所示:

Linux驱动开发学习归纳-2

/////////////////////********************************************************************************///////////////////////////

设备驱动模型由三大组件构成:总线、设备、驱动。

其中总线是一个抽象的总线,所有的设备和驱动都会挂接到一个总线上。然后设备需要和对应的驱动程序绑定后才能使用。

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 };
同理有驱动程序的注册和注销,还有驱动的属性。



Linux驱动开发学习归纳-2,布布扣,bubuko.com

Linux驱动开发学习归纳-2

上一篇:2、在Eclipse中使用JUnit4进行单元测试(中级篇)


下一篇:Linux的学习--使用PuTTY