设备驱动模型的核心数据结构
设备驱动模型依赖3个重要的结构,即kobject,kobj_type和kset。
kobject结构体
宏观上来说,设备驱动模型是一个设备和驱动组成的层次结构。在Linux系统中,kobject结构体是组成设备驱动模型的基本结构。kobject提供了最基本的设备对象管理能力,每一个在内核中注册的kobject对象都对应于sysfs文件系统中的一个目录。
struct kobject {
const char *name;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
struct kobj_type *ktype;
struct kernfs_node *sd;
struct kref kref;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
struct delayed_work release;
#endif
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;
};
设备属性 kobj_type
每个kobject对象都有一些属性,这些属性由kobj_type结构体表示。
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);
};
内核对象集合 kset
内核对象集kset主要将相关的内核对象组合在一起,kset是kobject的集合。换句话说,kset将相关的kobject收集到一个位置。每个注册的kset对应于sysfs目录。
kset_create_and_add() //函数创建和添加kset
kset_unregister() //函数删除kset
struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops;
};
//list 是kset中所有kobject的链表
//list_lock 保护链表访问的自旋锁
//kobj 表示该集合的基类
设备模型和sysfs
sysfs是非持久性虚拟文件系统,它提供系统的全局视图,并通过它们的kobject显示内核对象的层次结构(拓扑)。每个kobject显示为目录和目录中的文件,目录代表由相关kobject导出的内核变量。这些文件称为属性,可以读取或写入。
设备驱动模型的三大组件
设备驱动模型有三个重要组件,分别是总线,设备和驱动。
总线,从硬件结构上来讲,物理总线有数据总线和地址总线。物理总线是处理器与一个或者多个设备之间的通道。在设备驱动模型中,所有设备都通过总线连接,此处的总线与物理总线不同,总线是物理总线的一个抽象,同时还包含一些硬件中不存在的虚拟总线。在设备驱动模型中,驱动程序是附属在总线上的。
在设备驱动模型中,总线,设备和驱动三者之间紧密联系。在/sys目录下,有一个bus目录,所有的总线都在bus目录下。一般一个总线目录有一个设备目录,一个驱动目录和一些总线属性文件。
总线结构体
在Linux中,总线不仅是物理总线的抽象,还代表一些虚拟的总线。
struct bus_type {
const char *name;
const char *dev_name;
struct device *dev_root;
struct device_attribute *dev_attrs; /* use dev_groups instead */
const struct attribute_group **bus_groups;
const struct attribute_group **dev_groups;
const struct attribute_group **drv_groups;
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 (*online)(struct device *dev);
int (*offline)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
const struct dev_pm_ops *pm;
const struct iommu_ops *iommu_ops;
struct subsys_private *p;
struct lock_class_key lock_key;
};
设备结构体
struct device {
struct device *parent;
struct device_private *p;
struct kobject kobj;
const char *init_name; /* initial name of the device */
const 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 */
void *driver_data; /* Driver data, set and get with
dev_set/get_drvdata */
struct dev_pm_info power;
struct dev_pm_domain *pm_domain;
#ifdef CONFIG_PINCTRL
struct dev_pin_info *pins;
#endif
#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. */
unsigned long dma_pfn_offset;
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 */
#ifdef CONFIG_DMA_CMA
struct cma *cma_area; /* contiguous memory area for dma
allocations */
#endif
/* arch specific additions */
struct dev_archdata archdata;
struct device_node *of_node; /* associated device tree node */
struct fwnode_handle *fwnode; /* firmware device node */
dev_t devt; /* dev_t, creates the sysfs "dev" */
u32 id; /* device instance */
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);
struct iommu_group *iommu_group;
bool offline_disabled:1;
bool offline:1;
};
驱动结构体
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 */
const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;
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;
};