Linux设备驱动模型-Driver

来源:互联网 发布:替代共享文件夹软件 编辑:程序博客网 时间:2024/06/06 11:47

前言

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是否存在,不存在则会产生panicif ((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);                        //添加驱动到具体的busif (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;           //设置kseterror = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,                   "%s", drv->name);     //初始化和添加一个kobjectif (error)goto out_unregister;klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);   //添加驱动到klist_driver链表中if (drv->bus->p->drivers_autoprobe) {                       //驱动所属的bus是否支持自动probeerror = 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);                      //驱动引用计数减1bus_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);}}



0 0
原创粉丝点击