linux驱动模型——platform(1)
一.驱动模型包含什么?
1.1. 类class
1.1.2. 它能够自动创建/dev下的设备节点,不需要mknod /dev/xxx c x x创建。当然class还有其另外的作用,且自动创建设备节点的还有udev系统,udev是处于用户空间的,其自动创建设备节点也是依赖于sysfs文件系统中提供的class类
1.2. 总线bus
1.2.1. 总线是处理器和设备之间的通道。总线有多种类型,每种总线可以挂载多个设备
1.3. 设备device
1.3.1. 驱动程序是在CPU运行时,提供操作的软件接口。所有的设备必须有与之配套驱动程序才能正常工作。一个驱动程序可以驱动多个类似或者完全不同的设备。
1.4. 驱动driver
1.4.1. 设备就是连接在总线上的物理实体。设备是有功能之分的。具有相同功能的设备被归到一个类,如输入设备(鼠标,键盘,游戏杆等)。
1.5. 三者的关系
1.5.1. 总线上有两个重要的链表:1)设备(device)链表;2)驱动(driver)链表
1.5.2. 每次出现一个设备就要向总线汇报,每次出现一个驱动,也要向总线注册。系统初始化的时候,会扫描连接了哪些设备,为每一个设备建立起一个struct device的变量,并加入设备链表;每次注册一个驱动,就要准备一个struct device_driver结构的变量,并加入驱动链表。这样所有的设备都挂载到总线上,当加载驱动时,驱动就去总线上找到自己对应的设备,或者先把驱动注册上,来了一个设备就去总线找驱动。如果只有设备却没有对应的驱动,那么设备无法工作,如果只有驱动却没有设备,驱动也起不了任何作用。
1.5.3. 每种总线下面可以挂载许多设备。(通过kset devices)
1.5.4. 每种总线下可以用很多驱动。(通过包含一个kset drivers)
1.5.5. 每个驱动可以处理一个或多个设备。
1.6. 其它内容
1.6.1. 对象的引用计数
1.6.1.1. 通常一个内核对象被创建时,不可能知道该对象存活的时间。跟踪此对象生命周期的一个方法是使用引用计数。当内核中没有代码持有该对象的引用时,该对象将结束自己的有效生命周期,并且可以被删除
1.6.2. sysfs表述sysfs表述
1.6.2.1. 在sysfs中显示的每一个对象,都对应一个kobject,它被用来与内核交互并创建它的可见表述。
1.6.2.2. 数据结构关联:从整体上看,设备模型是一个友好而复杂的数据结构,通过在其间的大量连接而构成一个多层次的体系结构。Kobject实现了该结构并把它们聚合在一起
1.6.3. uevent事件处理
1.6.3.1. 当系统中的硬件被热插拔时,在kobject子系统控制下,将产生事件以通知用户空间
1.6.3.2. Kobjects 在内核中对应有一套申请,初始化,添加,注册,计数操作,释放等函数
二. 为什么需要设备驱动模型
2.1. linux 2.6版本中正式引入设备驱动模型,目的是在设备越来越多,功耗要求等新特性要求的情况下让驱动体系更易用、更优秀。
2.2. 设备驱动模型负责统一实现和维护一些特性,诸如:电源管理、热插拔、对象生命周期、用户空间和驱动空间的交互等基础设施
2.3. 设备驱动模型目的是简化驱动程序编写,但是客观上设备驱动模型本身设计和实现很复杂
三. 驱动模型中重要结构体
3.1. kobject结构体
3.1.1. 定义在linux/kobject.h中
struct kobject { const char *name; ///*kobject的名字,每个kobject都对应着sysfs下的一个文件夹,该名字也是对应的文件夹的名字。*/ struct list_head entry; ///*双向链表指针,用于将同一kset集合中的kobject链接到一起,便于访问*/ struct kobject *parent; ///*kobject对应的父kobject节点,在sysfs表现为上一级目录*/ struct kset *kset; ///*kobject所在的集合的指针,kset概念将在kset一节中描述*/ struct kobj_type *ktype; // /*kobject对象类型指针,随后将会介绍*/ struct sysfs_dirent *sd; // /*sd用于表示VFS文件系统的目录项,由此可见它是设备与文件之间的桥梁。在sysfs节会对此结构进行分析*/ struct kref kref; // /*对象引用计数器。 unsigned int state_initialized:1; unsigned int state_in_sysfs:1; unsigned int state_add_uevent_sent:1; unsigned int state_remove_uevent_sent:1; unsigned int uevent_suppress:1; };
3.2. kobj_type结构体
3.2.1. 很多书中简称为ktype,每一个kobject都需要绑定一个ktype来提供相应功能
3.2.2. 关键点1:sysfs_ops,提供该对象在sysfs中的操作方法(show和store)
3.2.3. 关键点2:attribute,提供在sysfs中以文件形式存在的属性,其实就是应用接口
struct kobj_type { void (*release)(struct kobject *kobj); const struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj); const void *(*namespace)(struct kobject *kobj); };
3.3. kset结构体
3.3.1. kset与kobject关系
/** * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem. * * A kset defines a group of kobjects. They can be individually * different "types" but overall these kobjects all want to be grouped * together and operated on in the same manner. ksets are used to * define the attribute callbacks and other common events that happen to * a kobject. * * @list: the list of all kobjects for this kset * @list_lock: a lock for iterating over the kobjects * @kobj: the embedded kobject for this kset (recursion, isn't it fun...) * @uevent_ops: the set of uevent operations for this kset. These are * called whenever a kobject has something happen to it so that the kset * can add new environment variables, or filter out the uevents if so * desired. */ struct kset { struct list_head list; spinlock_t list_lock; struct kobject kobj; const struct kset_uevent_ops *uevent_ops; };
3.4. bus_type结构体
3.4.1. match函数
3.4.1.1. match方法用来对总线下的device和driver进行匹配。理论上每种总线的匹配算法是不同的,但是实际上一般都是看name的
3.4.2. uevent函数
3.4.2.1. 产生事件以通知用户空间
struct bus_type { const char *name; struct bus_attribute *bus_attrs; struct device_attribute *dev_attrs; struct driver_attribute *drv_attrs; int (*match)(struct device *dev, struct device_driver *drv); int (*uevent)(struct device *dev, struct kobj_uevent_env *env); int (*probe)(struct device *dev); int (*remove)(struct device *dev); void (*shutdown)(struct device *dev); int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); const struct dev_pm_ops *pm; struct bus_type_private *p; };
3.5. device结构体
3.5.1. struct device是硬件设备在内核驱动框架中的抽象,是所有设备共有部分的集合
3.5.2. device_register用于向内核驱动框架注册一个设备
3.5.3. 通常device不会单独使用,而是被包含在一个具体设备结构体中,如struct usb_device有struct device成员
struct device { struct device *parent; struct device_private *p; struct kobject kobj; const char *init_name; /* initial name of the device */ struct device_type *type; struct mutex mutex; /* mutex to synchronize calls to * its driver. */ struct bus_type *bus; /* type of bus device is on */ struct device_driver *driver; /* which driver has allocated this device */ void *platform_data; /* Platform specific data, device core doesn't touch it */ struct dev_pm_info power; #ifdef CONFIG_NUMA int numa_node; /* NUMA node this device is close to */ #endif u64 *dma_mask; /* dma mask (if dma'able device) */ u64 coherent_dma_mask;/* Like dma_mask, but for alloc_coherent mappings as not all hardware supports 64 bit addresses for consistent allocations such descriptors. */ struct device_dma_parameters *dma_parms; struct list_head dma_pools; /* dma pools (if dma'ble) */ struct dma_coherent_mem *dma_mem; /* internal for coherent mem override */ /* arch specific additions */ struct dev_archdata archdata; #ifdef CONFIG_OF struct device_node *of_node; #endif dev_t devt; /* dev_t, creates the sysfs "dev" */ spinlock_t devres_lock; struct list_head devres_head; struct klist_node knode_class; struct class *class; const struct attribute_group **groups; /* optional groups */ void (*release)(struct device *dev); };
3.6. device_driver结构体
3.6.1. struct device_driver是驱动程序在内核驱动框架中的抽象
3.6.2. 关键元素1:name,驱动程序的名字,很重要,经常被用来作为驱动和设备的匹配依据
3.6.3. 关键元素2:probe,驱动程序的探测函数,用来检测一个设备是否可以被该驱动所管理
struct device_driver { const char *name; struct bus_type *bus; struct module *owner; const char *mod_name; /* used for built-in modules */ bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ #if defined(CONFIG_OF) const struct of_device_id *of_match_table; #endif int (*probe) (struct device *dev); int (*remove) (struct device *dev); void (*shutdown) (struct device *dev); int (*suspend) (struct device *dev, pm_message_t state); int (*resume) (struct device *dev); const struct attribute_group **groups; const struct dev_pm_ops *pm; struct driver_private *p; };
参考《朱老师.linux设备驱动模型》
索引文献:https://blog.csdn.net/lindonghai/article/details/8111744
索引文献:https://blog.csdn.net/zhoujiaxq/article/details/7646050