目录:
1 概述
2 总线bus_type
3 设备device
4 驱动device_driver
1 概述
Linux设备驱动模型采用分层分工的思想。设备驱动模型包含
总线、设备、驱动三大组件。
总线、设备、驱动三大组件之间的关系如下:
2 总线bus_type
在设备驱动模型中,所有的设备都是通过总线连接的。总线是物理总线的一种抽象,同时还包含一些硬件中不存在的虚拟总线。
在Linux设备驱动模型中,内核中的每一条总线都是通过bus_type来描述的:
-
--include/linux/device.h
-
-
struct bus_type {
-
const char *name; /* 总线名称 */
-
struct bus_attribute *bus_attrs; /* 总线属性和导出到sysfs中的方法 */
-
struct device_attribute *dev_attrs; /* 设备属性和导出到sysfs中的方法 */
-
struct driver_attribute *drv_attrs; /* 驱动属性和导出到sysfs中的方法 */
-
-
int (*match)(struct device *dev, struct device_driver *drv); /*匹配函数 检验参数2的驱动知否支持参数1中的设备*/
-
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; /* 总线的私有数据 */
-
};
相关资源:
(1)总线私有数据: struct bus_type_private
-
--driver/base/base.h
-
-
/**
-
* struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
-
* @subsys - the struct kset that defines this bus. This is the main kobject
-
* @drivers_kset - the list of drivers associated with this bus
-
* @devices_kset - the list of devices associated with this bus
-
* @klist_devices - the klist to iterate over the @devices_kset
-
* @klist_drivers - the klist to iterate over the @drivers_kset
-
* @bus_notifier - the bus notifier list for anything that cares about things
-
* on this bus.
-
* @bus - pointer back to the struct bus_type that this structure is associated
-
* with.
-
*
-
* This structure is the one that is the actual kobject allowing struct
-
* bus_type to be statically allocated safely. Nothing outside of the driver
-
* core should ever touch these fields.
-
*/
-
struct bus_type_private {
-
struct kset subsys; /* 代表bus子系统,里面的kobj是该bus的主kobj,也就是最顶层 */
-
struct kset *drivers_kset; /* 挂载在该总线上的所有驱动的集合 */
-
struct kset *devices_kset; /* 挂载在该总线上的所有设备的集合 */
-
struct klist klist_devices; /* 总线的设备列表 */
-
struct klist klist_drivers; /* 总线的驱动列表 */
-
struct blocking_notifier_head bus_notifier; /* 通知链表 */
-
unsigned int drivers_autoprobe:1; /* 设置是否在驱动注册时,自动探测设备 */
-
struct bus_type *bus; /* 总线和私有数据互指的指针 */
-
};
(2)设备与驱动匹配:
int (*match)(struct device *dev, struct device_driver *drv);
该函数是设备和驱动进行关联过程中的一个关键的函数,当一个总线上有新的设备或者驱动添加时,该函数就会被调用(可能多次)。一般使用name或id进行设备和驱动的匹配工作。
(2) 总线的注册:
总线构建完成好之后,第一个工作就是将总线注册到内核中,这个工作由下列函数来完成:
int bus_register (struct bus_type *bus)
-
--driver/base/bus.c
-
-
/**
-
* bus_register - register a bus with the system.
-
* @bus: bus.
-
*
-
* Once we have that, we registered the bus with the kobject
-
* infrastructure, then register the children subsystems it has:
-
* the devices and drivers that belong to the bus.
-
*/
-
int bus_register(struct bus_type *bus)
-
{
-
int retval;
-
struct bus_type_private *priv;
-
-
priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL); /* 构建总线私有数据 */
-
if (!priv)
-
return -ENOMEM;
-
-
priv->bus = bus; /* 总线与私有数据互指 */
-
bus->p = priv; /* 总线与私有数据互指 */
-
-
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier); /* 初始化通知链表 */
-
-
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name); /* 设置子系统的名称为总线名称 */
-
if (retval)
-
goto out;
-
-
priv->subsys.kobj.kset = bus_kset; /* 私有数据集合指向总线集合 */
-
priv->subsys.kobj.ktype = &bus_ktype; /* kobject属性文件,用于连接sys_ops */
-
priv->drivers_autoprobe = 1; /* 使能驱动自动加载 */
-
-
retval = kset_register(&priv->subsys);
-
if (retval)
-
goto out;
-
-
retval = bus_create_file(bus, &bus_attr_uevent);
-
if (retval)
-
goto bus_uevent_fail;
-
-
priv->devices_kset = kset_create_and_add("devices", NULL,
-
&priv->subsys.kobj);
-
if (!priv->devices_kset) {
-
retval = -ENOMEM;
-
goto bus_devices_fail;
-
}
-
-
priv->drivers_kset = kset_create_and_add("drivers", NULL,
-
if (!priv->drivers_kset) {
-
retval = -ENOMEM;
-
goto bus_drivers_fail;
-
}
-
-
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
-
klist_init(&priv->klist_drivers, NULL, NULL);
-
-
retval = add_probe_files(bus);
-
if (retval)
-
goto bus_probe_files_fail;
-
-
retval = bus_add_attrs(bus);
-
if (retval)
-
goto bus_attrs_fail;
-
-
pr_debug("bus: '%s': registered\n", bus->name);
-
return 0;
-
-
bus_attrs_fail:
-
remove_probe_files(bus);
-
bus_probe_files_fail:
-
kset_unregister(bus->p->drivers_kset);
-
bus_drivers_fail:
-
kset_unregister(bus->p->devices_kset);
-
bus_devices_fail:
-
bus_remove_file(bus, &bus_attr_uevent);
-
bus_uevent_fail:
-
kset_unregister(&bus->p->subsys);
-
kfree(bus->p);
-
out:
-
bus->p = NULL;
-
return retval;
-
}
-
EXPORT_SYMBOL_GPL(bus_register);
卸载总线由
int bus_unregister(struct bus_type *bus); 函数来完成。
3 设备device
在Linux设备驱动模型中,每一个设备都有一个device结构体来进行描述:
-
--include/linux/device.h
-
-
-
struct device {
-
struct device *parent;
-
-
struct device_private *p;
-
-
struct kobject kobj;
-
const char *init_name; /* initial name of the device ,to replace older version member bus_id
-
* reference to http://blog.chinaunix.net/uid-29767867-id-4536154.html
-
*/
-
struct device_type *type;
-
-
struct semaphore sem; /* semaphore 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 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;
-
-
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);
-
};
4 驱动device_driver
在设备驱动模型中,驱动使用device_driver结构体进行描述:
-
--include/linux/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 */
-
-
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;
-
};
阅读(1290) | 评论(0) | 转发(0) |