Linux驱动-驱动分离与分层
作者:互联网
#1 驱动分离
主机控制器驱动和设备驱动分离,引入中间API;
#2 驱动分层
分为驱动,总线,设备;
总线是Linux内核实现,用户需要实现驱动和设备;
驱动:具体的设备驱动;
设备:设备的属性,包括地址范围等信息;
##2.1 总线
数据结构 bus_type device.h
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);
int (*num_vf)(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;
};
使用总线时,需要向内核注册
extern int __must_check bus_register(struct bus_type *bus);
##2.2 驱动
数据结构 device_driver device.h
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 */
enum probe_type probe_type;
const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;
int (*probe) (struct device *dev);//驱动和设备匹配后,驱动里面的probe就会执行
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;
};
使用驱动时,使用如下函数注册:
extern int __must_check driver_register(struct device_driver *drv);
驱动注册过程:
driver_register(struct device_driver *drv)
bus_add_driver(drv);//将驱动添加到总线
driver_attach(struct device_driver *drv) //驱动绑定
bus_for_each_dev(struct bus_type *bus, struct device *start,void *data, int (*fn)(struct device *, void *)) //遍历总线上的每个设备,fn是函数指针,即为probe
__driver_attach //每个设备都调用,查看每个设备是否与驱动匹配
driver_match_device
drv->bus->match()==platform_match()
driver_probe_device(drv,dev)//driver_match_device匹配成功
really_probe
drv->probe //执行driver的probe函数
##2.3 设备
数据结构 device_type device.h
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_links_info links;
struct dev_pm_info power;
struct dev_pm_domain *pm_domain;
#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
struct irq_domain *msi_domain;
#endif
#ifdef CONFIG_PINCTRL
struct dev_pin_info *pins;
#endif
#ifdef CONFIG_GENERIC_MSI_IRQ
struct list_head msi_list;
#endif
#ifdef CONFIG_NUMA
int numa_node; /* NUMA node this device is close to */
#endif
const struct dma_map_ops *dma_ops;
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;
struct iommu_fwspec *iommu_fwspec;
bool offline_disabled:1;
bool offline:1;
};
使用设备时,使用如下函数注册:
extern int __must_check device_register(struct device *dev);
驱动注册过程:
device_add
bus_probe_device
device_initial_probe
__device_attach
device_bind_driver //dev->driver非空时(前面已经构造)
driver_sysfs_add //创建sysfs中driver和device指向对方的软链接。还有一个与它相对的函数drivers_sysfs_remove()。
driver_bound //实际将device加入驱动的设备链表。
bus_for_each_drv(dev->bus, NULL, &data,__device_attach_driver);//dev->driver为空时
__device_attach_driver
driver_match_device
drv->bus->match()==platform_match()
driver_probe_device(drv, dev)//driver_match_device匹配成功
really_probe
drv->probe //执行driver的probe函数
总结:驱动与设备匹配成功以后驱动的probe函数就会执行,probe函数就是驱动编写人员实现的。
标签:struct,bus,probe,driver,dev,分层,Linux,device,驱动 来源: https://blog.csdn.net/weixin_43338497/article/details/122376605