Linux设备模型之bus,device,driver分析

字体大小: 中小 标准 ->行高大小: 标准
内核的开发者将总线,设备,驱动这三者用软件思想抽象了出来,巧妙的建立了其间的关系,使之更形象化。结合前面所学的知识,总的来说其三者间的关系为bus有两条链表,分别用于挂接设备和驱动,指定了其自身bus的device或者driver最后都会分别连接到对应bus的这两条链表上,而总线又有其始端,为bus_kset,一个driver可以对应于几个设备,因此driver同样有其设备链表,用于挂接可以操作的设备,其自身也有bus挂接点,用于将自身挂接到对应bus(每个driver只属于一条总线),而对于device,一个设备只属于一条总线,只能有一个driver与其对应,因此对于device,都是单一的,一个driver挂接点,一个bus挂接点,device与bus相同的是都有始端,device为devices_kset,因此device的注册同时会出现在对应的bus目录和device总目录下。好了,下面就以源码为例分别分析一下bus,device,driver的注册过程。

一、bus的注册

      bus的注册比较简单,首先来看一下bus的结构:

      [cpp]

  1. struct bus_type {       const char      *name;                //名字   
  2.     struct bus_attribute    *bus_attrs;           //bus属性集        struct device_attribute *dev_attrs;           //device属性集   
  3.     struct driver_attribute *drv_attrs;           //driver属性集        int (*match)(struct device *dev, struct device_driver *drv);  
  4.     int (*uevent)(struct device *dev, struct kobj_uevent_env *env);       int (*probe)(struct device *dev);  
  5.     int (*remove)(struct device *dev);       void (*shutdown)(struct device *dev);  
  6.     int (*suspend)(struct device *dev, pm_message_t state);       int (*resume)(struct device *dev);  
  7.     const struct dev_pm_ops *pm;       struct bus_type_private *p;                   //bus的私有成员   
  8. };   //其中重点看一下私有成员结构体:   
  9. struct bus_type_private {       struct kset subsys;                           //bus内嵌的kset,代表其自身   
  10.     struct kset *drivers_kset;                           struct kset *devices_kset;  
  11.     struct klist klist_devices;                   //包含devices链表及其操作函数        struct klist klist_drivers;                   //driver链表及其操作函数   
  12.     struct blocking_notifier_head bus_notifier;       unsigned int drivers_autoprobe:1;              //匹配成功自动初始化标志   
  13.     struct bus_type *bus;                             };  

  无论是bus,driver,还是device其本身特征都放在私有成员里,其注册时,都会申请并填充这个结构体,下面具体分析一下bus的注册流程,从bus_register开始:

      [cpp]

  1. int bus_register(struct bus_type *bus)   {  
  2.     int retval;       struct bus_type_private *priv;  
  3.     priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);    //进入时bus_type->bus_type_private为NULL        if (!priv)                                                      //该函数主要是对其的设置   
  4.         return -ENOMEM;       priv->bus = bus;                                                //私有成员的bus回指该bus   
  5.     bus->p = priv;                                                  //初始化bus->p,即其私有属性        BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);  
  6.     retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);  //设置该bus的名字,bus是kset的封装        if (retval)  
  7.         goto out;                                                         //bus_kset即为所有bus的总起始端点   
  8.                                                       //围绕bus内嵌的kset初始化,和kset的初始化时围绕        priv->subsys.kobj.kset = bus_kset;                //kobj相似,没有parent时,就会用kset的kobj,此处即是   
  9.     priv->subsys.kobj.ktype = &bus_ktype;                    //属性操作级别统一为bus_ktype        priv->drivers_autoprobe = 1;                                    //设置该标志,当有driver注册时,会自动匹配devices   
  10.                                                                     //上的设备并用probe初始化,                                                                        //当有device注册时也同样找到  driver并会初始化   
  11.     retval = kset_register(&priv->subsys);                          //注册kset,创建目录结构,以及层次关系        if (retval)  
  12.         goto out;       retval = bus_create_file(bus, &bus_attr_uevent);                //当前bus目录下生成bus_attr_uevent属性文件   
  13.     if (retval)           goto bus_uevent_fail;  
  14.     priv->devices_kset = kset_create_and_add("devices", NULL,       //初始化bus目录下的devices目录,里面级联了该bus下设备,                             &priv->subsys.kobj);                    //仍然以kset为原型   
  15.     if (!priv->devices_kset) {           retval = -ENOMEM;  
  16.         goto bus_devices_fail;       }  
  17.     priv->drivers_kset = kset_create_and_add("drivers", NULL,       //初始化bus目录下的drivers目录,里面级联了该bus下设备的driver                             &priv->subsys.kobj);  
  18.     if (!priv->drivers_kset) {           retval = -ENOMEM;  
  19.         goto bus_drivers_fail;       }  
  20.     klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);  //初始化klist_devices里的操作函数成员        klist_init(&priv->klist_drivers, NULL, NULL);                            //klist_drivers里的操作函数置空   
  21.     retval = add_probe_files(bus);                                           //增加bus_attr_drivers_probe和bus_attr_drivers_autoprobe        if (retval)                                                              //属性文件   
  22.         goto bus_probe_files_fail;       retval = bus_add_attrs(bus);                                             //增加默认的属性文件   
  23.     if (retval)           goto bus_attrs_fail;  
  24.     pr_debug("bus: '%s': registered/n", bus->name);       return 0;  
  25. bus_attrs_fail:                                                               //以下为错误处理        remove_probe_files(bus);  
  26. bus_probe_files_fail:       kset_unregister(bus->p->drivers_kset);  
  27. bus_drivers_fail:       kset_unregister(bus->p->devices_kset);  
  28. bus_devices_fail:       bus_remove_file(bus, &bus_attr_uevent);  
  29. bus_uevent_fail:       kset_unregister(&bus->p->subsys);  
  30. out:       kfree(bus->p);  
  31.     bus->p = NULL;       return retval;  
  32. }  

   由此可见,bus又是kset的封装,bus_register主要完成了其私有成员bus_type_private的初始化,并初始化了其下的两个目录devices和drivers,及其属性文件,bus有个自己的根目录也就是bus有个起始端点,是bus_kset,经过此番的注册,bus目录下将会出现我们注册的bus,并且其下会有device和driver两个子目录,代表它下面的driver和device链表。

二、driver的注册

  下面看一下driver是怎么和bus关联起来的,首先看下driver的结构:

     [cpp]

  1. struct device_driver {       const char      *name;            //名字   
  2.     struct bus_type     *bus;        //其所在的bus        struct module       *owner;  
  3.     const char      *mod_name;  /* used for built-in modules */       bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */  
  4. #if defined(CONFIG_OF)        const struct of_device_id   *of_match_table;  
  5. #endif        int (*probe) (struct device *dev);        //匹配成功时可能会调用到的函数   
  6.     int (*remove) (struct device *dev);       void (*shutdown) (struct device *dev);  
  7.     int (*suspend) (struct device *dev, pm_message_t state);       int (*resume) (struct device *dev);  
  8.     const struct attribute_group **groups;       const struct dev_pm_ops *pm;  
  9.     struct driver_private *p;                 //私有成员,表示driver    };  
  10. //重点看下driver的私有成员    struct driver_private {  
  11.     struct kobject kobj;                      //代表driver自身        struct klist klist_devices;               //可以操控的设备链表   
  12.     struct klist_node knode_bus;              //挂接到bus的节点        struct module_kobject *mkobj;             //模块相关   
  13.     struct device_driver *driver;             //回指该driver    };  

  如同bus一样,重点的仍是可以代表其自身的私有属性,下面具体看一下driver的注册过程,从driver_register开始:

     [cpp]

  1. int driver_register(struct device_driver *drv)   {  
  2.     int ret;       struct device_driver *other;  
  3.     BUG_ON(!drv->bus->p);       if ((drv->bus->probe && drv->probe) ||           //driver和bus的同名操作函数如果同时存在,会出现警告   
  4.         (drv->bus->remove && drv->remove) ||         //并且会优先选用bus的            (drv->bus->shutdown && drv->shutdown))  
  5.         printk(KERN_WARNING "Driver '%s' needs updating - please use "               "bus_type methods/n", drv->name);  
  6.     other = driver_find(drv->name, drv->bus);        //进入bus的driver链表,确认该driver是否已经注册        if (other) {  
  7.         put_driver(other);                            //找到了再减少引用计数,并且报错退出            printk(KERN_ERR "Error: Driver '%s' is already registered, "  
  8.             "aborting.../n", drv->name);           return -EBUSY;  
  9.     }       ret = bus_add_driver(drv);                       //如果没有注册,那么把该driver加入所在bus   
  10.     if (ret)           return ret;  
  11.     ret = driver_add_groups(drv, drv->groups);       if (ret)  
  12.         bus_remove_driver(drv);       return ret;  
  13. }   /**************************************************** 
  14. × 跟踪一下driver_find(drv->name, drv->bus)  ****************************************************/  
  15. struct device_driver *driver_find(const char *name, struct bus_type *bus)   {  
  16.     struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);  //bus->p->drivers_kset代表bus下        struct driver_private *priv;                                    //的driver目录,此处会遍历bus的       
  17.                                                                     //driver链表,通过driver内嵌的        if (k) {                                                        //kobj名字比较   
  18.         priv = to_driver(k);           return priv->driver;                                 //如果找到同名的kobj那么返回该driver   
  19.     }       return NULL;  
  20. }   //看一下kset_find_obj吧:   
  21. struct kobject *kset_find_obj(struct kset *kset, const char *name)   {  
  22.     struct kobject *k;       struct kobject *ret = NULL;  
  23.     spin_lock(&kset->list_lock);       list_for_each_entry(k, &kset->list, entry) {                   //遍历bus下的driver链表,如果   
  24.         if (kobject_name(k) && !strcmp(kobject_name(k), name)) {   //找到那么返回找到的kobj,并且把                ret = kobject_get(k);                                  //该driver的kobj引用计数+1   
  25.             break;           }  
  26.     }       spin_unlock(&kset->list_lock);  
  27.     return ret;   }  
  28. /************************************************  × 再来跟踪一下driver_register里面的另外一个函数 
  29. × bus_add_driver(drv)  ************************************************/  
  30. int bus_add_driver(struct device_driver *drv)    {  
  31.     struct bus_type *bus;       struct driver_private *priv;  
  32.     int error = 0;       bus = bus_get(drv->bus);                                        //取得其所在bus的指针   
  33.     if (!bus)           return -EINVAL;  
  34.     pr_debug("bus: '%s': add driver %s/n", bus->name, drv->name);   //开始初始化这个driver的私有成员,                                                                        //和bus类似   
  35.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);       if (!priv) {  
  36.         error = -ENOMEM;           goto out_put_bus;  
  37.     }       klist_init(&priv->klist_devices, NULL, NULL);                   //设备操作函数清空,设备链表初始化   
  38.     priv->driver = drv;                                                    drv->p = priv;  
  39.     priv->kobj.kset = bus->p->drivers_kset;                          //kset指定到bus下面        error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,   //建立层次结构和属性文件   
  40.                      "%s", drv->name);       if (error)  
  41.         goto out_unregister;       if (drv->bus->p->drivers_autoprobe) {                            //bus的自动匹配如果设置为真,   
  42.         error = driver_attach(drv);                                  //那么到bus的devices上去匹配设备            if (error)  
  43.             goto out_unregister;       }  
  44.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);        //把driver挂接到bus的driver链表        module_add_driver(drv->owner, drv);  
  45.     error = driver_create_file(drv, &driver_attr_uevent);            //以下添加该driver相关属性文件        if (error) {  
  46.         printk(KERN_ERR "%s: uevent attr (%s) failed/n",               __func__, drv->name);  
  47.     }       error = driver_add_attrs(bus, drv);  
  48.     if (error) {           /* How the hell do we get out of this pickle? Give up */  
  49.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed/n",               __func__, drv->name);  
  50.     }       if (!drv->suppress_bind_attrs) {  
  51.         error = add_bind_files(drv);           if (error) {  
  52.             /* Ditto */               printk(KERN_ERR "%s: add_bind_files(%s) failed/n",  
  53.                 __func__, drv->name);           }  
  54.     }       kobject_uevent(&priv->kobj, KOBJ_ADD);  
  55.     return 0;   out_unregister:  
  56.     kobject_put(&priv->kobj);       kfree(drv->p);  
  57.     drv->p = NULL;   out_put_bus:  
  58.     bus_put(bus);       return error;  
  59. }   /**************************************************************** 
  60. × 接下来就剩下最终要的匹配函数driver_attach(drv)了,我们来看一下:  ****************************************************************/  
  61. int driver_attach(struct device_driver *drv)                            //遍历bus的设备链表找到    {                                                                       //合适的设备就调用__driver_attach,   
  62.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);      //NULL表示从头开始遍历    }    
  63. //============    int bus_for_each_dev(struct bus_type *bus, struct device *start,  
  64.              void *data, int (*fn)(struct device *, void *))   {  
  65.     struct klist_iter i;       struct device *dev;  
  66.     int error = 0;       if (!bus)  
  67.         return -EINVAL;       klist_iter_init_node(&bus->p->klist_devices, &i,              //进入bus的devices链表   
  68.                  (start ? &start->p->knode_bus : NULL));       while ((dev = next_device(&i)) && !error)                     //设备存在则调用fn即__driver_attach   
  69.         error = fn(dev, data);                                    //进行匹配        klist_iter_exit(&i);  
  70.     return error;   }   
  71. /*********************************************  × 接着看一下__driver_attach这个函数 
  72. *********************************************/   static int __driver_attach(struct device *dev, void *data)  
  73. {       struct device_driver *drv = data;  
  74.     if (!driver_match_device(drv, dev))                //进行匹配            return 0;  
  75.     if (dev->parent) /* Needed for USB */           device_lock(dev->parent);  
  76.     device_lock(dev);       if (!dev->driver)                               //如果设备没有指定driver   
  77.         driver_probe_device(drv, dev);              //那么需要初始化匹配到的这个设备        device_unlock(dev);  
  78.     if (dev->parent)           device_unlock(dev->parent);  
  79.     return 0;   }  
  80. /*********************************************  × 又遇到两个分支,囧,先看一下driver_match_device  
  81. *********************************************/    static inline int driver_match_device(struct device_driver *drv,      //bus的match存在就用bus的   
  82.                                       struct device *dev)             //,否则就直接匹配成功...    {                                                                     //match通常实现为首先扫描   
  83.     return drv->bus->match ? drv->bus->match(dev, drv) : 1;           //driver支持的id设备表,如果    }                                                                     //为NULL就用名字进行匹配   
  84. /************************************  × 再来看一下driver_probe_device这个函数  
  85. ************************************/    int driver_probe_device(struct device_driver *drv, struct device *dev)  
  86. {       int ret = 0;  
  87.     if (!device_is_registered(dev))                              //判断该设备是否已经注册            return -ENODEV;  
  88.     pr_debug("bus: '%s': %s: matched device %s with driver %s/n",            drv->bus->name, __func__, dev_name(dev), drv->name);  
  89.     pm_runtime_get_noresume(dev);       pm_runtime_barrier(dev);  
  90.     ret = really_probe(dev, drv);                               //调用really_probe        pm_runtime_put_sync(dev);  
  91.     return ret;   }  
  92. /************************************  × 看一下device_is_registered 
  93. ************************************/   static inline int device_is_registered(struct device *dev)  
  94. {       return dev->kobj.state_in_sysfs;                           //在sysfs中表示已经注册   
  95. }   /************************************ 
  96. × 再看really_probe  ************************************/  
  97. static int really_probe(struct device *dev, struct device_driver *drv)   {  
  98.     int ret = 0;       atomic_inc(&probe_count);  
  99.     pr_debug("bus: '%s': %s: probing driver %s with device %s/n",            drv->bus->name, __func__, drv->name, dev_name(dev));  
  100.     WARN_ON(!list_empty(&dev->devres_head));       dev->driver = drv;                                     //device的driver初始化成该driver   
  101.     if (driver_sysfs_add(dev)) {                                          printk(KERN_ERR "%s: driver_sysfs_add(%s) failed/n",  
  102.             __func__, dev_name(dev));           goto probe_failed;  
  103.     }                                                            //利用probe初始化设备   
  104.     if (dev->bus->probe) {                               //如果bus的probe存在就用bus的,            ret = dev->bus->probe(dev);                      //如果bus的不存在driver的存在   
  105.         if (ret)                                         //再用driver的                goto probe_failed;  
  106.     } else if (drv->probe) {           ret = drv->probe(dev);  
  107.         if (ret)               goto probe_failed;  
  108.     }       driver_bound(dev);                              //调用driver_bound进行绑定   
  109.     ret = 1;       pr_debug("bus: '%s': %s: bound device %s to driver %s/n",  
  110.          drv->bus->name, __func__, dev_name(dev), drv->name);       goto done;  
  111. probe_failed:       devres_release_all(dev);  
  112.     driver_sysfs_remove(dev);       dev->driver = NULL;  
  113.     if (ret != -ENODEV && ret != -ENXIO) {           /* driver matched but the probe failed */  
  114.         printk(KERN_WARNING                  "%s: probe of %s failed with error %d/n",  
  115.                drv->name, dev_name(dev), ret);       }  
  116.     /*       * Ignore errors returned by ->probe so that the next driver can try 
  117.      * its luck.       */  
  118.     ret = 0;   done:  
  119.     atomic_dec(&probe_count);       wake_up(&probe_waitqueue);  
  120.     return ret;   }  
  121. /**********************************  * 最后跟一下driver_bound(dev)这个函数 
  122. **********************************/   static void driver_bound(struct device *dev)  
  123. {       if (klist_node_attached(&dev->p->knode_driver)) {                   //判断是否已经绑定   
  124.         printk(KERN_WARNING "%s: device %s already bound/n",               __func__, kobject_name(&dev->kobj));  
  125.         return;       }  
  126.     pr_debug("driver: '%s': %s: bound to device '%s'/n", dev_name(dev),            __func__, dev->driver->name);  
  127.     klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);  //将设备添加                                                                                //到driver的链表   
  128.     if (dev->bus)           blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  
  129.                          BUS_NOTIFY_BOUND_DRIVER, dev);   }  
  130. //all end  

  总结一下,driver的注册,主要涉及将自身挂接到bus的driver链表,并将匹配到的设备加入自己的device链表,并且将匹配到的device的driver成员初始化为该driver,私有属性的driver节点也挂到driver的设备链表下,其中匹配函数是利用利用bus的match函数,该函数通常判断如果driver有id表,就查表匹配,如果没有就用driver和device名字匹配。当匹配成功后如果自动初始化标志允许则调用初始化函数probe,bus的probe优先级始终高于driver的。另外注意一点driver是没有总的起始端点的,driver不是可具体描述的事物。

   由于篇幅比较长,device的分析放到下一篇《linux设备模型之bus,device,driver分析<二>》   ^_^!

此文章由 http://www.ositren.com 收集整理 ,地址为: http://www.ositren.com/htmls/62546.html