前言
linux将所有的驱动抽象为struct device_driver结构。这样设计可以方便驱动程序更好编写,在编写驱动的时候只需要将此结构嵌入到具体的驱动中即可。
比如常见的结构: struct platform_driver结构
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
bool prevent_deferred_probe;
};
可以看到device_driver结构嵌入到platform_driver
数据结构
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;
};
name: 设备驱动的名称
bus: 设备驱动所属的总线
owner: 设备驱动的owner,通常为THIS_MODULE
suppress_bind_attrs: 通过sysfs操作设备驱动的bind/unbind,用来使能/关闭设备与驱动的自动匹配
of_device_id: device_tree中使用,用于匹配设备。
probe,remove: 当设备匹配/移除的时候,会调用设备驱动的probe/remove函数。
shutdown,suspend, resume: 代表设备驱动在调用管理的时候的回调函数。
groups: 设备驱动的属性。
p: 设备驱动的私有数据结构,通常可以将驱动的信息放入此结构中。
内核使用driver_attribute结构代表设备驱动的属性
struct driver_attribute {
struct attribute attr;
ssize_t (*show)(struct device_driver *driver, char *buf);
ssize_t (*store)(struct device_driver *driver, const char *buf,
size_t count);
};
设备驱动的属性,同样通过注册,最后调用到驱动的show和store函数。
和设备一样,内核也为设备驱动定义了一些驱动的宏属性,方便定义驱动属性。
#define DRIVER_ATTR(_name, _mode, _show, _store) \
struct driver_attribute driver_attr_##_name = __ATTR(_name, _mode, _show, _store)
#define DRIVER_ATTR_RW(_name) \
struct driver_attribute driver_attr_##_name = __ATTR_RW(_name)
#define DRIVER_ATTR_RO(_name) \
struct driver_attribute driver_attr_##_name = __ATTR_RO(_name)
#define DRIVER_ATTR_WO(_name) \
struct driver_attribute driver_attr_##_name = __ATTR_WO(_name)
设备驱动相关函数
- driver_register(注册一个驱动到系统)
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
BUG_ON(!drv->bus->p); //确定bus->p是否存在,不存在则会产生panic
if ((drv->bus->probe && drv->probe) || //警告信息,有新驱动的时候出出现此log。
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
printk(KERN_WARNING "Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);
other = driver_find(drv->name, drv->bus); //已经注册过的话,就打印已经注册的信息。
if (other) {
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
}
ret = bus_add_driver(drv); //添加驱动到具体的bus
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups); //添加驱动的属性
if (ret) {
bus_remove_driver(drv);
return ret;
}
kobject_uevent(&drv->p->kobj, KOBJ_ADD); //使用uevent机制,通知上层添加新的驱动
return ret;
}
A: 通过驱动的名称在所属的总线上查找,判断总线上是否已经有此驱动,防止重复注册。
struct device_driver *driver_find(const char *name, struct bus_type *bus)
{
struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
struct driver_private *priv;
if (k) {
/* Drop reference added by kset_find_obj() */
kobject_put(k);
priv = to_driver(k);
return priv->driver;
}
return NULL;
}
通过kset_find_obj函数,在drivers_set中查找是否已经注册,已经注册返回具体的驱动,如果没有注册返回NULL。
B: 将具体的驱动添加到所属的总线,这是注册驱动的核心函数。
int bus_add_driver(struct device_driver *drv)
{
struct bus_type *bus;
struct driver_private *priv;
int error = 0;
bus = bus_get(drv->bus);
if (!bus)
return -EINVAL;
pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
priv = kzalloc(sizeof(*priv), GFP_KERNEL); //申请driver_private内存
if (!priv) {
error = -ENOMEM;
goto out_put_bus;
}
klist_init(&priv->klist_devices, NULL, NULL);
priv->driver = drv; //将驱动存放到driver_private的driver中
drv->p = priv; //存放priv到device_driver的p中
priv->kobj.kset = bus->p->drivers_kset; //设置kset
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
"%s", drv->name); //初始化和添加一个kobject
if (error)
goto out_unregister;
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); //添加驱动到klist_driver链表中
if (drv->bus->p->drivers_autoprobe) { //驱动所属的bus是否支持自动probe
error = driver_attach(drv); //如果支持,则调用attach函数,这个函数在device中已经分析过
if (error)
goto out_unregister;
}
module_add_driver(drv->owner, drv);
error = driver_create_file(drv, &driver_attr_uevent); //创建驱动的Uevent属性
if (error) {
printk(KERN_ERR "%s: uevent attr (%s) failed\n",
__func__, drv->name);
}
error = driver_add_groups(drv, bus->drv_groups); //创建bus下的驱动属性
if (error) {
/* How the hell do we get out of this pickle? Give up */
printk(KERN_ERR "%s: driver_create_groups(%s) failed\n",
__func__, drv->name);
}
if (!drv->suppress_bind_attrs) { //添加绑定/不绑定的属性
error = add_bind_files(drv);
if (error) {
/* Ditto */
printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
__func__, drv->name);
}
}
return 0;
}
- driver_unregister(从系统中移除一个驱动)
void driver_unregister(struct device_driver *drv)
{
if (!drv || !drv->p) {
WARN(1, "Unexpected driver unregister!\n");
return;
}
driver_remove_groups(drv, drv->groups); //移除驱动的属性
bus_remove_driver(drv); //从所属的bus下移除该驱动
}
void bus_remove_driver(struct device_driver *drv)
{
if (!drv->bus)
return;
if (!drv->suppress_bind_attrs) //移除bind/unbind的属性
remove_bind_files(drv);
driver_remove_groups(drv, drv->bus->drv_groups); //移除设备属性
driver_remove_file(drv, &driver_attr_uevent); //移除uevent属性
klist_remove(&drv->p->knode_bus); //移除驱动节点,从klist_driver链表中
pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name);
driver_detach(drv); //解除设备与驱动联系
module_remove_driver(drv);
kobject_put(&drv->p->kobj); //驱动引用计数减1
bus_put(drv->bus); //总线引用计数减1
}
重点看下设备与对应的驱动是如何解除联系的。
void driver_detach(struct device_driver *drv)
{
struct device_private *dev_prv;
struct device *dev;
for (;;) {
spin_lock(&drv->p->klist_devices.k_lock); //加锁,防止别的驱动也在做相似的操作
if (list_empty(&drv->p->klist_devices.k_list)) { //如果设备链表为空,直接返回
spin_unlock(&drv->p->klist_devices.k_lock);
break;
}
dev_prv = list_entry(drv->p->klist_devices.k_list.prev, //对设备链表中的每个设备,调用__device_release_drive函数
struct device_private,
knode_driver.n_node);
dev = dev_prv->device;
get_device(dev);
spin_unlock(&drv->p->klist_devices.k_lock);
if (dev->parent) /* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if (dev->driver == drv)
__device_release_driver(dev);
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);
put_device(dev);
}
}
接下来分析__device_release_driver函数
static void __device_release_driver(struct device *dev)
{
struct device_driver *drv;
drv = dev->driver;
if (drv) {
pm_runtime_get_sync(dev);
driver_sysfs_remove(dev); //从sysfs中移除该驱动的信息
if (dev->bus) //调用bus下的通知机制,发送unbind_driver消息
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_UNBIND_DRIVER,
dev);
pm_runtime_put_sync(dev);
if (dev->bus && dev->bus->remove)
dev->bus->remove(dev); //调用bus下的remove函数
else if (drv->remove) //调用该驱动的remove函数
drv->remove(dev);
devres_release_all(dev); //释放该设备所占用的资源
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
klist_remove(&dev->p->knode_driver);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_UNBOUND_DRIVER,
dev);
}
}
原文作者:DragonKingZhu
原文地址:Linux设备驱动模型-Driver - 阅读清单 - 腾讯云开发者社区-腾讯云(版权归原文作者所有,侵权留言联系删除)