当前位置:   article > 正文

linux设备驱动模型——总线、设备、设备驱动_linux下的设备驱动模型:总线、驱动、设备的概念;

linux下的设备驱动模型:总线、驱动、设备的概念;

linux设备驱动模型如下所示(摘自《linux设备驱动开发详解》):

在Linux内核中,分别使用bus_type、device和device_driver来描述总线、设备和设备驱动之间的关系。首先根据SOC内部的总线关系分别分类出USB总线、PCI总线、I2C总线、SPI总线等常见总线,另外考虑到SOC系统中一些独立的外设控制器以及挂接在SOC内存空间的外设不依附前面这些总线,linux发明了一种虚拟总线,即platform总线,相应的设备称为platform_device,而驱动称为platform_driver。linux设备模型中,总线将设备和驱动绑定。在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每注册一个驱动的时候,会寻找与之区域的设备,而匹配由总线完成。接下来,以platform总线、platform_device和platform_driver三者的关系为例进行说明linux设备模型是如何通过总线管理设备与设备驱动的。

先来看下platform_device的注册,以s3c2440平台为例,在mach-smdk2440.c对平台设备进行了注册,如下:

  1. 首先根据SOC中有哪些设备定义平台设备数组:
  2. static struct platform_device *smdk2440_devices[] __initdata = {
  3. &s3c_device_usb,
  4. &s3c_device_lcd,
  5. &s3c_device_wdt,
  6. &s3c_device_i2c0,
  7. &s3c_device_iis,
  8. };
  9. 平台设备的结构体定义如下:
  10. struct platform_device {
  11.     const char    * name;
  12.     int        id;
  13.     struct device    dev;
  14.     u32        num_resources;
  15.     struct resource    * resource;
  16. };
  17. 接着通过platform_add_devices()注册到platform总线上,分别通过platform_device_register()单个注册每一个平台设备,其源码如下:
  18. int platform_device_register(struct platform_device *pdev)
  19. {
  20.     device_initialize(&pdev->dev);
  21.     return platform_device_add(pdev);
  22. }
  23. 详细看下platform_device_add的源码:
  24. 首先将dev.parent = &platform_bus;
  25. pdev->dev.bus = &platform_bus_type;
  26. 然后根据设备的num_resources往设备的parent上insert_resource(),最后调用device_add()将设备注册到device hierarchy。device_add的源码如下:
  27. int device_add(struct device *dev)
  28. {
  29.     struct device *parent = NULL;
  30.     struct class_interface *class_intf;
  31.     int error = -EINVAL;
  32.     dev = get_device(dev);
  33.     if (!dev)
  34.         goto done;
  35.     /* Temporarily support init_name if it is set.
  36.      * It will override bus_id for now */
  37.     if (dev->init_name)
  38.         dev_set_name(dev, "%s", dev->init_name);
  39.     if (!strlen(dev->bus_id))
  40.         goto done;
  41.     pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
  42.     parent = get_device(dev->parent);
  43.     setup_parent(dev, parent);
  44.     /* use parent numa_node */
  45.     if (parent)
  46.         set_dev_node(dev, dev_to_node(parent));
  47.     /* first, register with generic layer. */
  48.     error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev_name(dev));
  49.     if (error)
  50.         goto Error;
  51.     /* notify platform of device entry */
  52.     if (platform_notify)
  53.         platform_notify(dev);
  54.     error = device_create_file(dev, &uevent_attr);
  55.     if (error)
  56.         goto attrError;
  57.     if (MAJOR(dev->devt)) {
  58.         error = device_create_file(dev, &devt_attr);
  59.         if (error)
  60.             goto ueventattrError;
  61.         error = device_create_sys_dev_entry(dev);
  62.         if (error)
  63.             goto devtattrError;
  64.     }
  65.     error = device_add_class_symlinks(dev);
  66.     if (error)
  67.         goto SymlinkError;
  68.     error = device_add_attrs(dev);
  69.     if (error)
  70.         goto AttrsError;
  71.     error = bus_add_device(dev);
  72.     if (error)
  73.         goto BusError;
  74.     error = dpm_sysfs_add(dev);
  75.     if (error)
  76.         goto DPMError;
  77.     device_pm_add(dev);
  78.     /* Notify clients of device addition.  This call must come
  79.      * after dpm_sysf_add() and before kobject_uevent().
  80.      */
  81.     if (dev->bus)
  82.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
  83.                          BUS_NOTIFY_ADD_DEVICE, dev);
  84.     kobject_uevent(&dev->kobj, KOBJ_ADD);
  85.     bus_attach_device(dev);
  86.     if (parent)
  87.         klist_add_tail(&dev->knode_parent, &parent->klist_children);
  88.     if (dev->class) {
  89.         mutex_lock(&dev->class->p->class_mutex);
  90.         /* tie the class to the device */
  91.         klist_add_tail(&dev->knode_class,
  92.                    &dev->class->p->class_devices);
  93.         /* notify any interfaces that the device is here */
  94.         list_for_each_entry(class_intf,
  95.                     &dev->class->p->class_interfaces, node)
  96.             if (class_intf->add_dev)
  97.                 class_intf->add_dev(dev, class_intf);
  98.         mutex_unlock(&dev->class->p->class_mutex);
  99.     }
  100. done:
  101.     ......
  102. }
  103. 该函数先判断dev是否为空,再调用setup_parent()为dev寻找父节点,再调用kobject_add()往父节点添加kobject节点,
  104. 然后分别调用device_create_file为设备节点创建sysfs的设备节点,再创建一些软连接符号,接着执行bus_attach_device(dev)为设备
  105. 寻找对应的设备驱动,详细看下该函数的内容:
  106. void bus_attach_device(struct device *dev)
  107. {
  108.     struct bus_type *bus = dev->bus;
  109.     int ret = 0;
  110.     if (bus) {
  111.         if (bus->p->drivers_autoprobe)
  112.             ret = device_attach(dev);
  113.         WARN_ON(ret < 0);
  114.         if (ret >= 0)
  115.             klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
  116.     }
  117. }
  118. 首先会判断drivers_autoprobe是否为真,然后调用device_attach(),成功后再调用 klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);将设备
  119. 添加到klist_devices链表中,下面详细看下device_attach函数的内容:
  120. int device_attach(struct device *dev)
  121. {
  122.     int ret = 0;
  123.     down(&dev->sem);
  124.     if (dev->driver) {
  125.         ret = device_bind_driver(dev);
  126.         if (ret == 0)
  127.             ret = 1;
  128.         else {
  129.             dev->driver = NULL;
  130.             ret = 0;
  131.         }
  132.     } else {
  133.         ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
  134.     }
  135.     up(&dev->sem);
  136.     return ret;
  137. }
  138. 如果dev已经有驱动关联了,就调用device_bind_driver,否则就调用bus_for_each_drv()从设备
  139. 所依附的总线上遍历已注册的驱动。该函数中会回调__device_attach()来为设备寻找匹配的驱动,其源码如下:
  140. static int __device_attach(struct device_driver *drv, void *data)
  141. {
  142.     struct device *dev = data;
  143.     return driver_probe_device(drv, dev);
  144. }
  145. int driver_probe_device(struct device_driver *drv, struct device *dev)
  146. {
  147.     int ret = 0;
  148.     if (!device_is_registered(dev))
  149.         return -ENODEV;
  150.     if (drv->bus->match && !drv->bus->match(dev, drv))
  151.         goto done;
  152.     pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
  153.          drv->bus->name, __func__, dev_name(dev), drv->name);
  154.     ret = really_probe(dev, drv);
  155. done:
  156.     return ret;
  157. }
  158. 可以看到,最后匹配dev与drv的函数是在drv所依附的bus->match()中匹配的,由于这里注册的是platform总线,看下
  159. platform总线的定义,如下:
  160. struct bus_type platform_bus_type = {
  161.     .name        = "platform",
  162.     .dev_attrs    = platform_dev_attrs,
  163.     .match        = platform_match,
  164.     .uevent        = platform_uevent,
  165.     .pm        = PLATFORM_PM_OPS_PTR,
  166. };
  167. 其match方法如下:
  168. static int platform_match(struct device *dev, struct device_driver *drv)
  169. {
  170.     struct platform_device *pdev;
  171.     pdev = container_of(dev, struct platform_device, dev);
  172.     return (strcmp(pdev->name, drv->name) == 0);
  173. }
  174. match()方法只是判断dev->name与drv->name是否相同。现在回过来看driver_probe_device()匹配成功的内容,
  175. 若dev与drv匹配成功,则会调用really_probe(dev, drv),其源码如下:
  176. static int really_probe(struct device *dev, struct device_driver *drv)
  177. {
  178.     int ret = 0;
  179.     atomic_inc(&probe_count);
  180.     dev->driver = drv;
  181.     if (driver_sysfs_add(dev)) {
  182.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
  183.             __func__, dev_name(dev));
  184.         goto probe_failed;
  185.     }
  186.     if (dev->bus->probe) {
  187.         ret = dev->bus->probe(dev);
  188.         if (ret)
  189.             goto probe_failed;
  190.     } else if (drv->probe) {
  191.         ret = drv->probe(dev);
  192.         if (ret)
  193.             goto probe_failed;
  194.     }
  195.     driver_bound(dev);
  196.     ret = 1;
  197.     pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
  198.          drv->bus->name, __func__, dev_name(dev), drv->name);
  199.     goto done;
  200. probe_failed:
  201. ......
  202.     return ret;
  203. }
  204. 首先将dev->driver指向drv,然后判断dev->bus->probe与drv->probe方法是否存在,在platform总线上没有probe方法,
  205. 因此会执行drv->probe()方法,即platform_driver的probe方法。

分析好了platform_device的注册过程,接下来看下platform_driver的注册过程,以s3c2440平台的s3c_device_wdt平台设备的平台驱动为例,平台驱动通过platform_driver_register注册平台驱动,先看下s3c_device_wdt的平台驱动定义,如下:

  1. static struct platform_driver s3c2410wdt_driver = {
  2. .probe = s3c2410wdt_probe,
  3. .remove = s3c2410wdt_remove,
  4. .shutdown = s3c2410wdt_shutdown,
  5. .suspend = s3c2410wdt_suspend,
  6. .resume = s3c2410wdt_resume,
  7. .driver = {
  8. .owner = THIS_MODULE,
  9. .name = "s3c2410-wdt",
  10. },
  11. };
  12. 可以看到.driver.name字段与s3c_device_wdt的平台设备的.name字段相同,当platform总线的match方法匹配出平台设备与平台驱动后就调用平台驱动
  13. 的probe方法了,本例就是s3c2410wdt_driver的.probe方法。下面来详细看下平台驱动的注册,即platform_driver_register函数的内容:
  14. int platform_driver_register(struct platform_driver *drv)
  15. {
  16.     drv->driver.bus = &platform_bus_type;
  17.     if (drv->probe)
  18.         drv->driver.probe = platform_drv_probe;
  19.     if (drv->remove)
  20.         drv->driver.remove = platform_drv_remove;
  21.     if (drv->shutdown)
  22.         drv->driver.shutdown = platform_drv_shutdown;
  23.     if (drv->suspend)
  24.         drv->driver.suspend = platform_drv_suspend;
  25.     if (drv->resume)
  26.         drv->driver.resume = platform_drv_resume;
  27.     return driver_register(&drv->driver);
  28. }
  29. 首先将drv->driver.bus设为platform_bus_type,然后判断drv的probe、remove、shutdown、suspend和resume字段是否为空,若为空,则使用平台总线对应的
  30. 默认平台驱动接口,然后调用driver_register注册平台驱动,其源码如下:
  31. int driver_register(struct device_driver *drv)
  32. {
  33.     int ret;
  34.     struct device_driver *other;
  35.     if ((drv->bus->probe && drv->probe) ||
  36.         (drv->bus->remove && drv->remove) ||
  37.         (drv->bus->shutdown && drv->shutdown))
  38.         printk(KERN_WARNING "Driver '%s' needs updating - please use "
  39.             "bus_type methods\n", drv->name);
  40.     other = driver_find(drv->name, drv->bus);
  41.     if (other) {
  42.         put_driver(other);
  43.         printk(KERN_ERR "Error: Driver '%s' is already registered, "
  44.             "aborting...\n", drv->name);
  45.         return -EEXIST;
  46.     }
  47.     ret = bus_add_driver(drv);
  48.     if (ret)
  49.         return ret;
  50.     ret = driver_add_groups(drv, drv->groups);
  51.     if (ret)
  52.         bus_remove_driver(drv);
  53.     return ret;
  54. }
  55. 首先根据drv->bus和drv->name从drv依附的bus中寻找是否已经注册了drv->name的平台驱动,若没注册,则调用bus_add_driver()注册驱动,其源码如下:
  56. int bus_add_driver(struct device_driver *drv)
  57. {
  58.     struct bus_type *bus;
  59.     struct driver_private *priv;
  60.     int error = 0;
  61.     bus = bus_get(drv->bus);
  62.     if (!bus)
  63.         return -EINVAL;
  64.     pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
  65.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  66.     if (!priv) {
  67.         error = -ENOMEM;
  68.         goto out_put_bus;
  69.     }
  70.     klist_init(&priv->klist_devices, NULL, NULL);
  71.     priv->driver = drv;
  72.     drv->p = priv;
  73.     priv->kobj.kset = bus->p->drivers_kset;
  74.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
  75.                      "%s", drv->name);
  76.     if (error)
  77.         goto out_unregister;
  78.     if (drv->bus->p->drivers_autoprobe) {
  79.         error = driver_attach(drv);
  80.         if (error)
  81.             goto out_unregister;
  82.     }
  83.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
  84.     module_add_driver(drv->owner, drv);
  85.     error = driver_create_file(drv, &driver_attr_uevent);
  86.     if (error) {
  87.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",
  88.             __func__, drv->name);
  89.     }
  90.     error = driver_add_attrs(bus, drv);
  91.     if (error) {
  92.         /* How the hell do we get out of this pickle? Give up */
  93.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
  94.             __func__, drv->name);
  95.     }
  96.     error = add_bind_files(drv);
  97.     if (error) {
  98.         /* Ditto */
  99.         printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
  100.             __func__, drv->name);
  101.     }
  102.     kobject_uevent(&priv->kobj, KOBJ_ADD);
  103.     return error;
  104. out_unregister:
  105. ......
  106. }
  107. 该函数首先根据drv->bus获得drv依附的bus,再创建一个priv结构体来存放drv在内核中需要表示的相关数据结构,接着判断
  108. drv->bus->p->drivers_autoprobe是否为真,若为真,则调用driver_attach将驱动与某个平台设备进行关联。然后通过klist_add_tail将
  109. priv所指向的drv添加到klist_drivers链表中,最后会调用driver_create_file等为drv创建sysfs对应的设备驱动节点。
  110. 下面来详细看下driver_attach中是如何将驱动与某个平台设备进行关联的,其源码如下:
  111. int driver_attach(struct device_driver *drv)
  112. {
  113.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
  114. }
  115. 在bus_for_each_dev中会回调__driver_attach()函数,其源码如下:
  116. static int __driver_attach(struct device *dev, void *data)
  117. {
  118.     struct device_driver *drv = data;
  119.     if (drv->bus->match && !drv->bus->match(dev, drv))
  120.         return 0;
  121.     if (dev->parent)    /* Needed for USB */
  122.         down(&dev->parent->sem);
  123.     down(&dev->sem);
  124.     if (!dev->driver)
  125.         driver_probe_device(drv, dev);
  126.     up(&dev->sem);
  127.     if (dev->parent)
  128.         up(&dev->parent->sem);
  129.     return 0;
  130. }
  131. 该函数首先判断drv所依附的bus->match()函数是否存在,若存在,则调用其match()函数来匹配设备与设备驱动。由于platform总线的
  132. match()方法只是判断platform_device与platform_driver的名字是否相同,若相同,则判断dev->driver是否已关联。若没有关联,
  133. 则调用driver_probe_device(drv, dev),该函数在上面platform_device注册过程中已分析过,其最终调用really_probe(dev, drv),
  134. 继而执行drv的probe方法。
分析完platform_device与platform_driver之间是如何通过platform bus进行关联的过程后,下面再来分析platform bus的注册流程,即platform_bus_init()的源码(在platform.c文件中):

  1. int __init platform_bus_init(void)
  2. {
  3. int error;
  4. error = device_register(&platform_bus);
  5. if (error)
  6. return error;
  7. error = bus_register(&platform_bus_type);
  8. if (error)
  9. device_unregister(&platform_bus);
  10. return error;
  11. }
  12. struct device platform_bus = {
  13.     .init_name    = "platform",
  14. };
  15. struct bus_type platform_bus_type = {
  16.     .name        = "platform",
  17.     .dev_attrs    = platform_dev_attrs,
  18.     .match        = platform_match,
  19.     .uevent        = platform_uevent,
  20.     .pm        = PLATFORM_PM_OPS_PTR,
  21. };
  22. 在platform_bus的初始化函数中,首先会通过device_register()注册platform_bus,再通过bus_register()注册platform_bus_type。分别来看下两个注册
  23. 函数的内容。device_register()的源码如下:
  24. int device_register(struct device *dev)
  25. {
  26.     device_initialize(dev);
  27.     return device_add(dev);
  28. }
  29. 该函数的内容与平台设备的注册过程没什么区别,只不过此时注册的是platform_bus,没有指明parent节点,因此将platform_bus作为一个节点。接着再来看下
  30. bus_register()的内容,如下:
  31. int bus_register(struct bus_type *bus)
  32. {
  33.     int retval;
  34.     struct bus_type_private *priv;
  35.     priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
  36.     if (!priv)
  37.         return -ENOMEM;
  38.     priv->bus = bus;
  39.     bus->p = priv;
  40.     BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
  41.     retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
  42.     if (retval)
  43.         goto out;
  44.     priv->subsys.kobj.kset = bus_kset;
  45.     priv->subsys.kobj.ktype = &bus_ktype;
  46.     priv->drivers_autoprobe = 1;
  47.     retval = kset_register(&priv->subsys);
  48.     if (retval)
  49.         goto out;
  50.     retval = bus_create_file(bus, &bus_attr_uevent);
  51.     if (retval)
  52.         goto bus_uevent_fail;
  53.     priv->devices_kset = kset_create_and_add("devices", NULL,
  54.                          &priv->subsys.kobj);
  55.     if (!priv->devices_kset) {
  56.         retval = -ENOMEM;
  57.         goto bus_devices_fail;
  58.     }
  59.     priv->drivers_kset = kset_create_and_add("drivers", NULL,
  60.                          &priv->subsys.kobj);
  61.     if (!priv->drivers_kset) {
  62.         retval = -ENOMEM;
  63.         goto bus_drivers_fail;
  64.     }
  65.     klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
  66.     klist_init(&priv->klist_drivers, NULL, NULL);
  67.     retval = add_probe_files(bus);
  68.     if (retval)
  69.         goto bus_probe_files_fail;
  70.     retval = bus_add_attrs(bus);
  71.     if (retval)
  72.         goto bus_attrs_fail;
  73.     pr_debug("bus: '%s': registered\n", bus->name);
  74.     return 0;
  75. bus_attrs_fail:
  76.     ......
  77. }
  78. 该函数中会申请priv结构体来存储bus在内核中需要表示的数据结构,可以看到:
  79. priv->subsys.kobj.kset = bus_kset;
  80.     priv->subsys.kobj.ktype = &bus_ktype;
  81.     priv->drivers_autoprobe = 1;
  82. 这里将drivers_autoprobe设为1,且kset为bus_kset,ktype为bus_ktype。然后调用kset_register()注册platform_bus的kset,接着调用
  83. bus_create_file()为bus创建sysfs的总线节点,然后调用priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);
  84. 和priv->drivers_kset = kset_create_and_add("drivers", NULL,&priv->subsys.kobj)为总线分别创建device和driver的kset容器。然后分别
  85. 初始化priv->klist_devices和priv->klist_drivers链表,后面设备和设备驱动的注册会分别添加到klist_devices和klist_drivers两个链表中。在驱动注册过程中
  86. bus_for_each_dev()函数中会遍历klist_devices来寻找该驱动对应的device;在设备注册过程中的bus_for_each_drv()函数会遍历klist_drivers来寻找该设备
  87. 对应的driver。
从上述的platform_bus的注册过程可以看到,其实platform_bus的注册分为platform_bus设备注册和platform_bus_type注册。平台总线本身也是一种设备。相当于一个顶层设备,然后其他子设备挂接到该设备下。由于linux设备驱动模型与sysfs的关系,后序需要详细分析kobject和kset在整个linux设备驱动模型中的管理流程。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/444492
推荐阅读
相关标签
  

闽ICP备14008679号