Chinaunix首页 | 论坛 | 博客
  • 博客访问: 329962
  • 博文数量: 67
  • 博客积分: 668
  • 博客等级: 上士
  • 技术积分: 1591
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-16 22:08
文章分类

全部博文(67)

文章存档

2015年(1)

2014年(13)

2013年(28)

2012年(23)

2011年(2)

分类: LINUX

2012-06-25 17:13:55

三,驱动

device_driver结构体的定义include/linux/Device.h

点击(此处)折叠或打开

  1. struct device_driver {
  2.     const char        *name;
  3.     struct bus_type        *bus;

  4.     struct module        *owner;
  5.     const char        *mod_name;    /* used for built-in modules */

  6.     bool suppress_bind_attrs;    /* disables bind/unbind via sysfs */

  7.     int (*probe) (struct device *dev);
  8.     int (*remove) (struct device *dev);
  9.     void (*shutdown) (struct device *dev);
  10.     int (*suspend) (struct device *dev, pm_message_t state);
  11.     int (*resume) (struct device *dev);
  12.     const struct attribute_group **groups;

  13.     const struct dev_pm_ops *pm;

  14.     struct driver_private *p;
  15. };
driver_register函数在driver/base/Driver.c中,此函数注册driver到相应总线。

点击(此处)折叠或打开

  1. /**
  2.  * driver_register - register driver with bus
  3.  * @drv: driver to register
  4.  *
  5.  * We pass off most of the work to the bus_add_driver() call,
  6.  * since most of the things we have to do deal with the bus
  7.  * structures.
  8.  */
  9. int driver_register(struct device_driver *drv)
  10. {
  11.     int ret;
  12.     struct device_driver *other;

  13.     BUG_ON(!drv->bus->p);

  14.     if ((drv->bus->probe && drv->probe) ||
  15.      (drv->bus->remove && drv->remove) ||
  16.      (drv->bus->shutdown && drv->shutdown))
  17.         printk(KERN_WARNING "Driver '%s' needs updating - please use "
  18.             "bus_type methods\n", drv->name);            

  19.     other = driver_find(drv->name, drv->bus);    //(1)
  20.     if (other) {
  21.         put_driver(other);
  22.         printk(KERN_ERR "Error: Driver '%s' is already registered, "
  23.             "aborting...\n", drv->name);
  24.         return -EBUSY;
  25.     }

  26.     ret = bus_add_driver(drv);            //(2)
  27.     if (ret)
  28.         return ret;
  29.     ret = driver_add_groups(drv, drv->groups);    
  30.     if (ret)
  31.         bus_remove_driver(drv);
  32.     return ret;
  33. }
(1)在对应的总线上,通过驱动的名字查找驱动。如果查找到就说明已经注册过了。函数定义如下。

点击(此处)折叠或打开

  1. struct device_driver *driver_find(const char *name, struct bus_type *bus)
  2. {    //kset_find_obj在相应的set上查找kobject。函数分析在关于kobject的博文中有分析
  3.     struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);    
  4.     struct driver_private *priv;

  5.     if (k) {
  6.         priv = to_driver(k);
  7.         return priv->driver;
  8.     }
  9.     return NULL;
  10. }
(2)bus_add_driver函数向驱动关联的总线添加这个驱动,会生成目录和连接文件等
分析bus_add_driver函数,这个函数在drivers/base/Bus.c

点击(此处)折叠或打开

  1. int bus_add_driver(struct device_driver *drv)
  2. {
  3.     struct bus_type *bus;
  4.     struct driver_private *priv;
  5.     int error = 0;

  6.     bus = bus_get(drv->bus);        //获取并增加bus的引用
  7.     if (!bus)
  8.         return -EINVAL;

  9.     pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

  10.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);    //获取driver_private的空间(1)
  11.     if (!priv) {
  12.         error = -ENOMEM;
  13.         goto out_put_bus;
  14.     }
  15.     klist_init(&priv->klist_devices, NULL, NULL);
  16.     priv->driver = drv;    //driver_private中的驱动指向drv
  17.     drv->p = priv;    //drv的私有结构(driver_private)指向这个私有结构priv
  18.     priv->kobj.kset = bus->p->drivers_kset;
  19.             //driver的kobject的kset 和 bus的kobject的kset 是相同的
  20.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
  21.                  "%s", drv->name);                    //将这个driver的kobject注册进sysfs系统
  22.     if (error)
  23.         goto out_unregister;

  24.     if (drv->bus->p->drivers_autoprobe) {
  25.         error = driver_attach(drv);        //将寻找这个总线上匹配相应的设备(2)
  26.         if (error)
  27.             goto out_unregister;
  28.     }
  29.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); //将driver添加到bus的list列表中
  30.     module_add_driver(drv->owner, drv);    //添加到module(?)

  31.     error = driver_create_file(drv, &driver_attr_uevent);//在驱动目录下添加uevent文件
  32.     if (error) {
  33.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",
  34.             __func__, drv->name);
  35.     }
  36.     error = driver_add_attrs(bus, drv);    //将bus的属性都在driver目录下生成相应的属性文件
  37.     if (error) {
  38.         /* How the hell do we get out of this pickle? Give up */
  39.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
  40.             __func__, drv->name);
  41.     }
  42.     //
  43.     if (!drv->suppress_bind_attrs) {
  44.         error = add_bind_files(drv);    //生成bind和unbind文件,可以手动实现driver和device的之间的匹配和移除
  45.         if (error) {
  46.             /* Ditto */
  47.             printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
  48.                 __func__, drv->name);
  49.         }
  50.     }

  51.     kobject_uevent(&priv->kobj, KOBJ_ADD);//通知用户空间uevent
  52.     return 0;

  53. out_unregister:
  54.     kfree(drv->p);
  55.     drv->p = NULL;
  56.     kobject_put(&priv->kobj);
  57. out_put_bus:
  58.     bus_put(bus);
  59.     return error;
  60. }
(1)driver_private定义

点击(此处)折叠或打开

  1. struct driver_private {
  2.     struct kobject kobj;        //driver的kobject结构体
  3.     struct klist klist_devices;    //
  4.     struct klist_node knode_bus;
  5.     struct module_kobject *mkobj;
  6.     struct device_driver *driver;    //一般再指向包含自身的驱动
  7. };
(2)寻找总线上此驱动对应的设备

点击(此处)折叠或打开

  1. int driver_attach(struct device_driver *drv)
  2. {
  3.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
  4. }
  5. /**
  6.  * bus_for_each_dev - device iterator.
  7.  * @bus: bus type.
  8.  * @start: device to start iterating from.
  9.  * @data: data for the callback.
  10.  * @fn: function to be called for each device.
  11.  *
  12.  * Iterate over @bus's list of devices, and call @fn for each,
  13.  * passing it @data. If @start is not NULL, we use that device to
  14.  * begin iterating from.
  15.  *
  16.  * We check the return of @fn each time. If it returns anything
  17.  * other than 0, we break out and return that value.
  18.  *
  19.  * NOTE: The device that returns a non-zero value is not retained
  20.  * in any way, nor is its refcount incremented. If the caller needs
  21.  * to retain this data, it should do so, and increment the reference
  22.  * count in the supplied callback.
  23.  */
  24. int bus_for_each_dev(struct bus_type *bus, struct device *start,
  25.          void *data, int (*fn)(struct device *, void *))
  26. {
  27.     struct klist_iter i;
  28.     struct device *dev;
  29.     int error = 0;

  30.     if (!bus)
  31.         return -EINVAL;

  32.     klist_iter_init_node(&bus->p->klist_devices, &i,
  33.              (start ? &start->p->knode_bus : NULL));
  34.     while ((dev = next_device(&i)) && !error)
  35.         error = fn(dev, data);        //遍历链表上每个设备,调用传来的函数(这里是__driver_attach)匹配
  36.     klist_iter_exit(&i);
  37.     return error;
  38. }

点击(此处)折叠或打开

  1. static int __driver_attach(struct device *dev, void *data)
  2. {
  3.     struct device_driver *drv = data;

  4.     /*
  5.      * Lock device and try to bind to it. We drop the error
  6.      * here and always return 0, because we need to keep trying
  7.      * to bind to devices and some drivers will return an error
  8.      * simply if it didn't support the device.
  9.      *
  10.      * driver_probe_device() will spit a warning if there
  11.      * is an error.
  12.      */

  13.     if (!driver_match_device(drv, dev))    //是否匹配,不匹配就返回,匹配就继续下面的操作(1)
  14.         return 0;

  15.     if (dev->parent)    /* Needed for USB */
  16.         down(&dev->parent->sem);
  17.     down(&dev->sem);
  18.     if (!dev->driver)    //如果设备还没有关联驱动
  19.         driver_probe_device(drv, dev);    //关联驱动和设备(2)
  20.     up(&dev->sem);
  21.     if (dev->parent)
  22.         up(&dev->parent->sem);

  23.     return 0;
  24. }
(1)使用驱动总线上的match方法,检测设备和驱动是否匹配

点击(此处)折叠或打开

  1. static inline int driver_match_device(struct device_driver *drv,
  2.                  struct device *dev)
  3. {
  4.     return drv->bus->match ? drv->bus->match(dev, drv) : 1;    //如果bus有match方法,则调用。否则返回1
  5. }
(2)关联设备和驱动函数

点击(此处)折叠或打开

  1. /**
  2.  * driver_probe_device - attempt to bind device & driver together
  3.  * @drv: driver to bind a device to
  4.  * @dev: device to try to bind to the driver
  5.  *
  6.  * This function returns -ENODEV if the device is not registered,
  7.  * 1 if the device is bound sucessfully and 0 otherwise.
  8.  *
  9.  * This function must be called with @dev->sem held. When called for a
  10.  * USB interface, @dev->parent->sem must be held as well.
  11.  */
  12. int driver_probe_device(struct device_driver *drv, struct device *dev)
  13. {
  14.     int ret = 0;

  15.     if (!device_is_registered(dev))        //此设备是否已经注册
  16.         return -ENODEV;

  17.     pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
  18.          drv->bus->name, __func__, dev_name(dev), drv->name);

  19.     pm_runtime_get_noresume(dev);
  20.     pm_runtime_barrier(dev);
  21.     ret = really_probe(dev, drv); //看名字 真实的probe
  22.     pm_runtime_put_sync(dev);

  23.     return ret;
  24. }

点击(此处)折叠或打开

  1. static int really_probe(struct device *dev, struct device_driver *drv)
  2. {
  3.     int ret = 0;

  4.     atomic_inc(&probe_count);
  5.     pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
  6.          drv->bus->name, __func__, drv->name, dev_name(dev));
  7.     WARN_ON(!list_empty(&dev->devres_head));

  8.     dev->driver = drv;
  9.     if (driver_sysfs_add(dev)) {    //此函数将在driver和device目录下创建相互的连接文件
  10.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
  11.             __func__, dev_name(dev));
  12.         goto probe_failed;
  13.     }

  14.     if (dev->bus->probe) {        //有bus上的probe则调用它
  15.         ret = dev->bus->probe(dev);
  16.         if (ret)
  17.             goto probe_failed;
  18.     } else if (drv->probe) {    //否则若有驱动的probe则调用它
  19.         ret = drv->probe(dev);
  20.         if (ret)
  21.             goto probe_failed;
  22.     }

  23.     driver_bound(dev);
  24.     ret = 1;
  25.     pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
  26.          drv->bus->name, __func__, dev_name(dev), drv->name);
  27.     goto done;

  28. probe_failed:
  29.     devres_release_all(dev);
  30.     driver_sysfs_remove(dev);
  31.     dev->driver = NULL;

  32.     if (ret != -ENODEV && ret != -ENXIO) {
  33.         /* driver matched but the probe failed */
  34.         printk(KERN_WARNING
  35.          "%s: probe of %s failed with error %d\n",
  36.          drv->name, dev_name(dev), ret);
  37.     }
  38.     /*
  39.      * Ignore errors returned by ->probe so that the next driver can try
  40.      * its luck.
  41.      */
  42.     ret = 0;
  43. done:
  44.     atomic_dec(&probe_count);
  45.     wake_up(&probe_waitqueue);
  46.     return ret;
  47. }
上述函数的主要调用关系
driver_register
driver_find
bus_add_driver
kobject_init_and_add
driver_attach
bus_for_each_dev
__driver_attach
driver_match_device
driver_probe_device
really_probe
四、类
类是设备的高层视图,所有创建的类都将在sys/class目录中。类是系统向用户层导出信息的一个不错的方法。
类结构的定义

点击(此处)折叠或打开

  1. struct class {
  2.     const char        *name;
  3.     struct module        *owner;

  4.     struct class_attribute        *class_attrs;
  5.     struct device_attribute        *dev_attrs;
  6.     struct kobject            *dev_kobj;

  7.     int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
  8.     char *(*devnode)(struct device *dev, mode_t *mode);

  9.     void (*class_release)(struct class *class);
  10.     void (*dev_release)(struct device *dev);

  11.     int (*suspend)(struct device *dev, pm_message_t state);
  12.     int (*resume)(struct device *dev);

  13.     const struct dev_pm_ops *pm;

  14.     struct class_private *p;
  15. };
创建类的函数如下

点击(此处)折叠或打开

  1. struct class *__class_create(struct module *owner, const char *name,
  2.              struct lock_class_key *key)
  3. {
  4.     struct class *cls;
  5.     int retval;

  6.     cls = kzalloc(sizeof(*cls), GFP_KERNEL);
  7.     if (!cls) {
  8.         retval = -ENOMEM;
  9.         goto error;
  10.     }

  11.     cls->name = name;
  12.     cls->owner = owner;
  13.     cls->class_release = class_create_release;

  14.     retval = __class_register(cls, key);
  15.     if (retval)
  16.         goto error;

  17.     return cls;

  18. error:
  19.     kfree(cls);
  20.     return ERR_PTR(retval);
  21. }
创建一个类是创建了一个容器,我们最主要的还是创建类下面的设备。在类下创建设备的函数是。
在旧的linux版本中有专门创建类设备的函数class_device_create,而新的版本中没有了(我现在看的2.6.31就没有)。
我们先看旧版本的
类设备结构定义

点击(此处)折叠或打开

  1. struct class_device {
  2.     struct list_head    node;

  3.     struct kobject        kobj;
  4.     struct class        * class;    /* required */
  5.     dev_t            devt;        /* dev_t, creates the sysfs "dev" */
  6.     struct class_device_attribute *devt_attr;
  7.     struct class_device_attribute uevent_attr;
  8.     struct device        * dev;        /* not necessary, but nice to have */
  9.     void            * class_data;    /* class-specific data */
  10.     struct class_device    *parent;    /* parent of this child device, if there is one */

  11.     void    (*release)(struct class_device *dev);
  12.     int    (*uevent)(struct class_device *dev, char **envp,
  13.              int num_envp, char *buffer, int buffer_size);
  14.     char    class_id[BUS_ID_SIZE];    /* unique to this class */
  15. };
创建类设备函数class_device_create,此函数调用关系如下
class_device_create
class_device_initialize
class_device_add

新版本的linux没有了class_device,class_device_create等。可以直接使用device_create,调用顺序为
device_create
device_create_vargs
device_register
device_initialize
device_add
阅读(2022) | 评论(2) | 转发(5) |
给主人留下些什么吧!~~

gc50842012-06-27 08:42:55

网络传奇: 博主写的不错.....
谢谢

网络传奇2012-06-26 15:09:10

博主写的不错