linux设备驱动模型之device

来源:互联网 发布:android 打开移动网络 编辑:程序博客网 时间:2024/06/05 22:35
系统中任一设备都有一个device对象描述,我们先来看一下它在内核中的表示:
[cpp] view plain copy
 print?
  1. struct device {  
  2.     struct device       *parent;//父设备  
  3.   
  4.     struct device_private   *p;//设备的私有数据  
  5.   
  6.     struct kobject kobj;//表示该设备并把它链接到设备模型中的kobject  
  7.     const char      *init_name;//初始化名字  
  8.     struct device_type  *type;//设备的类型  
  9.   
  10.     struct mutex        mutex;  //用于互斥访问  
  11.   
  12.     struct bus_type *bus;   //  标识了该设备链接在哪一个总线上  
  13.     struct device_driver *driver;   // 管理该设备的驱动程序,一个设备只能有一个驱动程序  
  14.     void        *platform_data; //平台的特定数据   
  15.     struct dev_pm_info  power;  
  16.   
  17. #ifdef CONFIG_NUMA  
  18.     int     numa_node;  /* NUMA node this device is close to */  
  19. #endif  
  20.     u64     *dma_mask;  //指向设备DMA屏蔽字  
  21.     u64     coherent_dma_mask;//设备一致性DMA的屏蔽字  
  22.   
  23.     struct device_dma_parameters *dma_parms;  
  24.   
  25.     struct list_head    dma_pools;  //聚集的DMA缓冲池  
  26.     struct dma_coherent_mem *dma_mem; //指向设备所使用的一致性DMA存储器描述符的指针  
  27.     struct dev_archdata archdata;  
  28. #ifdef CONFIG_OF  
  29.     struct device_node  *of_node;  
  30. #endif  
  31.   
  32.     dev_t           devt;   /* dev_t, creates the sysfs "dev" */  
  33.   
  34.     spinlock_t      devres_lock;//用于互斥访问设备  
  35.     struct list_head    devres_head;  
  36.   
  37.     struct klist_node   knode_class;  
  38.     struct class        *class;//指向属于的类  
  39.     const struct attribute_group **groups;  /* optional groups */  
  40.   
  41.     void    (*release)(struct device *dev);//释放设备描述符的回调函数  
  42. };  
[cpp] view plain copy
 print?
  1. struct device_private {  
  2.     struct klist klist_children;//该设备的子设备链表  
  3.     struct klist_node knode_parent;//此结点将device链入device的parent的children链表  
  4.     struct klist_node knode_driver;//此结点将device链入device对应的driver的devices链表  
  5.     struct klist_node knode_bus;//此结点将device链入到对应的bus的devices链表  
  6.     void *driver_data;//设备驱动程序使用的私有数据  
  7.     struct device *device;//指向与之相关的device  
  8. };  

可以看到device_private 的作用主要是把device链接入n个链表,以方便查找设备。
有关device,最重要的一个函数就是device_register,它的作用主要是注册设备驱动程序,搜寻驱动drv对应的设备,并与之关联。
[cpp] view plain copy
 print?
  1. int device_register(struct device *dev)  
  2. {  
  3.     device_initialize(dev);//初始化dev  
  4.     return device_add(dev); //添加dev  
  5. }  
这个函数比较简单,主要是调用另外两个函数进行设备的初始化和添加操作,首先看下device_initialize
[cpp] view plain copy
 print?
  1. void device_initialize(struct device *dev)  
  2. {  
  3.     dev->kobj.kset = devices_kset;//设置设备的kobject所属集合,devices_kset其实在第一层,sys/devices/  
  4.     kobject_init(&dev->kobj, &device_ktype);  //初始化设备的kobject  
  5.     INIT_LIST_HEAD(&dev->dma_pools); //初始化设备的DMA池,用于传递大数据  
  6.     mutex_init(&dev->mutex); //初始化互斥锁  
  7.     lockdep_set_novalidate_class(&dev->mutex);  
  8.     spin_lock_init(&dev->devres_lock);//初始化自旋锁,用于同步子设备链表  
  9.     INIT_LIST_HEAD(&dev->devres_head);   //初始化子设备链表头  
  10.     device_pm_init(dev);// 此函数初始化device的power域  
  11.     set_dev_node(dev, -1);  
  12. }  
devices_kset是所有dev的kset,也就是所有dev都被链接在该kset下,这个kset是在设备初始化的时候创建的
[cpp] view plain copy
 print?
  1. int __init devices_init(void)  
  2. {  
  3.     devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);  
  4.     ......  
  5.   
  6.  char_kobj_err:  
  7.     kobject_put(sysfs_dev_block_kobj);  
  8.  block_kobj_err:  
  9.     kobject_put(dev_kobj);  
  10.  dev_kobj_err:  
  11.     kset_unregister(devices_kset);  
  12.     return -ENOMEM;  
  13. }  
parent=NULL,所以生成/sys/devices目录
[cpp] view plain copy
 print?
  1. void device_initialize(struct device *dev)  
  2. {  
  3.     dev->kobj.kset = devices_kset;//设置设备的kobject所属集合,devices_kset其实在第一层,sys/devices/  
  4.     kobject_init(&dev->kobj, &device_ktype);  //初始化设备的kobject  
  5.     INIT_LIST_HEAD(&dev->dma_pools); //初始化设备的DMA池,用于传递大数据  
  6.     mutex_init(&dev->mutex); //初始化互斥锁  
  7.     lockdep_set_novalidate_class(&dev->mutex);  
  8.     spin_lock_init(&dev->devres_lock);//初始化自旋锁,用于同步子设备链表  
  9.     INIT_LIST_HEAD(&dev->devres_head);   //初始化子设备链表头  
  10.     device_pm_init(dev);// 此函数初始化device的power域  
  11.     set_dev_node(dev, -1);  
  12. }  
device_initialize对设备结构进行初始化,这里的ktype是device_ktype,kset是devices_kset
接着调用device_add添加到驱动模型中去。
[cpp] view plain copy
 print?
  1. int device_add(struct device *dev)  
  2. {  
  3.     struct device *parent = NULL;  
  4.     struct class_interface *class_intf;  
  5.     int error = -EINVAL;  
  6.   
  7.     dev = get_device(dev);//增加设备的kobject的引用计数  
  8.     if (!dev)  
  9.         goto done;  
  10.   
  11.     if (!dev->p) {  
  12.         error = device_private_init(dev);//初始化dev的私有成员,及其链表操作函数  
  13.         if (error)  
  14.             goto done;  
  15.     }  
  16.   
  17.     /* 
  18.      * for statically allocated devices, which should all be converted 
  19.      * some day, we need to initialize the name. We prevent reading back 
  20.      * the name, and force the use of dev_name() 
  21.      */  
  22.     if (dev->init_name) {  //保存设备名,以后需要获取时使用dev_name函数获取  
  23.         dev_set_name(dev, "%s", dev->init_name);  
  24.         dev->init_name = NULL;  
  25.     }  
  26.   
  27.     if (!dev_name(dev)) {  
  28.         error = -EINVAL;  
  29.         goto name_error;  
  30.     }  
  31.   
  32.     pr_debug("device: '%s': %s\n", dev_name(dev), __func__);  
  33.   
  34.     parent = get_device(dev->parent);//返回父节点,增加父节点引用计数,如果有返回,没有返回NULL  
  35.     setup_parent(dev, parent);//以上层devices为准重设dev->kobj.parent  
  36.   
  37.     /* use parent numa_node */  
  38.     if (parent)  
  39.         set_dev_node(dev, dev_to_node(parent));  
  40.   
  41.     /* first, register with generic layer. */  
  42.     /* we require the name to be set before, and pass NULL */  
  43.     error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); //设置dev->kobj的名字和父对象,并建立相应目录  
  44.     if (error)  
  45.         goto Error;  
  46.   
  47.     /* notify platform of device entry */  
  48.     if (platform_notify)  
  49.         platform_notify(dev);  
  50.       
  51.     error = device_create_file(dev, &uevent_attr); //建立uevent属性文件  
  52.     if (error)  
  53.         goto attrError;  
  54.   
  55.     if (MAJOR(dev->devt)) {  
  56.         error = device_create_file(dev, &devt_attr);//在sys下产生dev属性文件  
  57.         if (error)  
  58.             goto ueventattrError;  
  59.   
  60.         error = device_create_sys_dev_entry(dev);  
  61.         if (error)  
  62.             goto devtattrError;  
  63.   
  64.         devtmpfs_create_node(dev);  
  65.     }  
  66.     //建立subsystem链接文件连接到所属class  
  67.     error = device_add_class_symlinks(dev);  
  68.     if (error)  
  69.         goto SymlinkError;  
  70.     //添加dev的属性描述文件  
  71.     error = device_add_attrs(dev);  
  72.     if (error)  
  73.         goto AttrsError;  
  74.     error = bus_add_device(dev); //添加链接文件至所属bus  
  75.     if (error)  
  76.         goto BusError;  
  77.     error = dpm_sysfs_add(dev); //添加power文件  
  78.     if (error)  
  79.         goto DPMError;  
  80.     device_pm_add(dev);  
  81.   
  82.     /* Notify clients of device addition.  This call must come 
  83.      * after dpm_sysf_add() and before kobject_uevent(). 
  84.      */  
  85.     if (dev->bus)  
  86.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  
  87.                          BUS_NOTIFY_ADD_DEVICE, dev);  
  88.   
  89.     kobject_uevent(&dev->kobj, KOBJ_ADD);//向用户空间发出KOBJ_ADD 事件  
  90.     bus_probe_device(dev);//检测驱动中有无适合的设备进行匹配,现在只添加了设备,还没有加载驱动,所以不会进行匹配  
  91.     if (parent)  
  92.         klist_add_tail(&dev->p->knode_parent, //把该设备的节点挂到其父节点的链表  
  93.                    &parent->p->klist_children);  
  94.   
  95.     if (dev->class) {  
  96.         mutex_lock(&dev->class->p->class_mutex);  
  97.         /* tie the class to the device */  
  98.         klist_add_tail(&dev->knode_class,  
  99.                    &dev->class->p->class_devices);  
  100.   
  101.         /* notify any interfaces that the device is here */  
  102.         list_for_each_entry(class_intf,  
  103.                     &dev->class->p->class_interfaces, node)  
  104.             if (class_intf->add_dev)  
  105.                 class_intf->add_dev(dev, class_intf);  
  106.         mutex_unlock(&dev->class->p->class_mutex);  
  107.     }  
  108. done:  
  109.     put_device(dev);  
  110.     return error;  
  111.  DPMError:  
  112.     bus_remove_device(dev);  
  113.  BusError:  
  114.     device_remove_attrs(dev);  
  115.  AttrsError:  
  116.     device_remove_class_symlinks(dev);  
  117.  SymlinkError:  
  118.     if (MAJOR(dev->devt))  
  119.         devtmpfs_delete_node(dev);  
  120.     if (MAJOR(dev->devt))  
  121.         device_remove_sys_dev_entry(dev);  
  122.  devtattrError:  
  123.     if (MAJOR(dev->devt))  
  124.         device_remove_file(dev, &devt_attr);  
  125.  ueventattrError:  
  126.     device_remove_file(dev, &uevent_attr);  
  127.  attrError:  
  128.     kobject_uevent(&dev->kobj, KOBJ_REMOVE);  
  129.     kobject_del(&dev->kobj);  
  130.  Error:  
  131.     cleanup_device_parent(dev);  
  132.     if (parent)  
  133.         put_device(parent);  
  134. name_error:  
  135.     kfree(dev->p);  
  136.     dev->p = NULL;  
  137.     goto done;  
  138. }  
这里看一下设备匹配:
[cpp] view plain copy
 print?
  1. void bus_probe_device(struct device *dev)//匹配driver以及初始化过程  
  2. {  
  3.     struct bus_type *bus = dev->bus;  
  4.     int ret;  
  5.   
  6.     if (bus && bus->p->drivers_autoprobe) {//设置了自动匹配初始化那么就开始匹配  
  7.         ret = device_attach(dev);  
  8.         WARN_ON(ret < 0);  
  9.     }  
  10. }  
device_attach进行匹配操作。
[cpp] view plain copy
 print?
  1. int device_attach(struct device *dev)  
  2. {  
  3.     int ret = 0;  
  4.   
  5.     device_lock(dev);  
  6.     if (dev->driver) {//默认指定了driver就直接绑定  
  7.         ret = device_bind_driver(dev);  
  8.         if (ret == 0)  
  9.             ret = 1;  
  10.         else {  
  11.             dev->driver = NULL;  
  12.             ret = 0;  
  13.         }  
  14.     } else {//没有指定就进行遍历匹配  
  15.         pm_runtime_get_noresume(dev);  
  16.         ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);  
  17.         pm_runtime_put_sync(dev);  
  18.     }  
  19.     device_unlock(dev);  
  20.     return ret;  
  21. }  
device_bind_driver进行驱动的绑定。
[cpp] view plain copy
 print?
  1. int device_bind_driver(struct device *dev)  
  2. {  
  3.     int ret;  
  4.     //将driver和dev使用link,链接到一起,使他们真正相关  
  5.     ret = driver_sysfs_add(dev);  
  6.     if (!ret)  
  7.         driver_bound(dev);//将私有成员的driver节点挂到了driver的设备链表  
  8.     return ret;  
  9. }  
driver_sysfs_add建立软链,它会在驱动目录下建立一个到设备的同名链接,并且在设备目录下建立一个名为 driver.到驱动的链接
[cpp] view plain copy
 print?
  1. static int driver_sysfs_add(struct device *dev)  
  2. {  
  3.     int ret;  
  4.   
  5.     ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,//驱动目录下dev->kobj目录链接到dev->kobj  
  6.               kobject_name(&dev->kobj));  
  7.     if (ret == 0) {  
  8.         ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,//在dev->kobj目录下的driver目录链接到其驱动目录  
  9.                     "driver");  
  10.         if (ret)  
  11.             sysfs_remove_link(&dev->driver->p->kobj,  
  12.                     kobject_name(&dev->kobj));  
  13.     }  
  14.     return ret;  
  15. }  
driver_bound将私有成员的driver节点挂到了driver的设备链表
[cpp] view plain copy
 print?
  1. static void driver_bound(struct device *dev)  
  2. {  
  3.     if (klist_node_attached(&dev->p->knode_driver)) {//判断是否已经绑定  
  4.         printk(KERN_WARNING "%s: device %s already bound\n",  
  5.             __func__, kobject_name(&dev->kobj));  
  6.         return;  
  7.     }  
  8.   
  9.     pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),  
  10.          __func__, dev->driver->name);  
  11.   
  12.     klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); //将设备添加到driver的链表  
  13.   
  14.     if (dev->bus)  
  15.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  
  16.                          BUS_NOTIFY_BOUND_DRIVER, dev);//通知bus上所有设备bound消息  
  17. }  
回到device_attach,如果没有指定就进行遍历匹配
[cpp] view plain copy
 print?
  1. int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,  
  2.              void *data, int (*fn)(struct device_driver *, void *))  
  3. {  
  4.     struct klist_iter i;  
  5.     struct device_driver *drv;  
  6.     int error = 0;  
  7.   
  8.     if (!bus)  
  9.         return -EINVAL;  
  10.   
  11.     klist_iter_init_node(&bus->p->klist_drivers, &i,//和driver遍历device类似,从头开始遍历bus的driver链表  
  12.                  start ? &start->p->knode_bus : NULL); //发现一个driver就调用fn即__device_attach进行匹配  
  13.     while ((drv = next_driver(&i)) && !error)  
  14.         error = fn(drv, data);  
  15.     klist_iter_exit(&i);  
  16.     return error;  
  17. }  
再来看下__device_attach
[cpp] view plain copy
 print?
  1. static int __device_attach(struct device_driver *drv, void *data)  
  2. {  
  3.     struct device *dev = data;  
  4.   
  5.     if (!driver_match_device(drv, dev))//匹配条件检查  
  6.         return 0;  
  7.   
  8.     return driver_probe_device(drv, dev);//进行真正的匹配操作  
  9. }  
看下driver_match_device
[cpp] view plain copy
 print?
  1. static inline int driver_match_device(struct device_driver *drv,  
  2.                       struct device *dev)//bus的match存在就用bus的否则就直接匹配成功.match通常实现为首先扫描driver支持的id设备表,如果为NULL就用名字进行匹配  
  3. {  
  4.     return drv->bus->match ? drv->bus->match(dev, drv) : 1;  
  5. }  
再来看下driver_probe_device,进行匹配操作
[cpp] view plain copy
 print?
  1. int driver_probe_device(struct device_driver *drv, struct device *dev)  
  2. {  
  3.     int ret = 0;  
  4.   
  5.     if (!device_is_registered(dev))//判断该设备是否已经注册  
  6.         return -ENODEV;  
  7.   
  8.     pr_debug("bus: '%s': %s: matched device %s with driver %s\n",  
  9.          drv->bus->name, __func__, dev_name(dev), drv->name);  
  10.   
  11.     pm_runtime_get_noresume(dev);  
  12.     pm_runtime_barrier(dev);  
  13.     ret = really_probe(dev, drv);//调用really_probe  
  14.     pm_runtime_put_sync(dev);  
  15.   
  16.     return ret;  
  17. }  
首先调用查看是否已经注册:
[cpp] view plain copy
 print?
  1. static inline int device_is_registered(struct device *dev)  
  2. {  
  3.     return dev->kobj.state_in_sysfs; //在sysfs中表示已经注册  
  4. }  
再调用 really_probe进行匹配
[cpp] view plain copy
 print?
  1. static int really_probe(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     int ret = 0;  
  4.   
  5.     atomic_inc(&probe_count);  
  6.     pr_debug("bus: '%s': %s: probing driver %s with device %s\n",  
  7.          drv->bus->name, __func__, drv->name, dev_name(dev));  
  8.     WARN_ON(!list_empty(&dev->devres_head));  
  9.   
  10.     dev->driver = drv; //device的driver初始化成该driver  
  11.     if (driver_sysfs_add(dev)) {//驱动目录下建立一个到设备的同名链接,并且在设备目录下建立一个名为 driver.到驱动的链接  
  12.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",  
  13.             __func__, dev_name(dev));  
  14.         goto probe_failed;  
  15.     }  
  16.   
  17.     if (dev->bus->probe) { //利用probe初始化设备  
  18.         ret = dev->bus->probe(dev); //如果bus的probe存在就用bus的,  
  19.         if (ret)  
  20.             goto probe_failed;  
  21.     } else if (drv->probe) {//如果bus的不存在driver的存在  
  22.         ret = drv->probe(dev);//再用driver的  
  23.         if (ret)  
  24.             goto probe_failed;  
  25.     }  
  26.   
  27.     driver_bound(dev);//调用driver_bound进行绑定  
  28.     ret = 1;  
  29.     pr_debug("bus: '%s': %s: bound device %s to driver %s\n",  
  30.          drv->bus->name, __func__, dev_name(dev), drv->name);  
  31.     goto done;  
  32.   
  33. probe_failed:  
  34.     devres_release_all(dev);  
  35.     driver_sysfs_remove(dev);  
  36.     dev->driver = NULL;  
  37.   
  38.     if (ret != -ENODEV && ret != -ENXIO) {  
  39.         /* driver matched but the probe failed */  
  40.         printk(KERN_WARNING  
  41.                "%s: probe of %s failed with error %d\n",  
  42.                drv->name, dev_name(dev), ret);  
  43.     }  
  44.     /* 
  45.      * Ignore errors returned by ->probe so that the next driver can try 
  46.      * its luck. 
  47.      */  
  48.     ret = 0;  
  49. done:  
  50.     atomic_dec(&probe_count);  
  51.     wake_up(&probe_waitqueue);  
  52.     return ret;  
  53. }  
再看下driver_bound
[cpp] view plain copy
 print?
  1. static void driver_bound(struct device *dev)  
  2. {  
  3.     if (klist_node_attached(&dev->p->knode_driver)) {//判断是否已经绑定  
  4.         printk(KERN_WARNING "%s: device %s already bound\n",  
  5.             __func__, kobject_name(&dev->kobj));  
  6.         return;  
  7.     }  
  8.   
  9.     pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),  
  10.          __func__, dev->driver->name);  
  11.   
  12.     klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); //将设备添加到driver的链表  
  13.   
  14.     if (dev->bus)  
  15.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  
  16.                          BUS_NOTIFY_BOUND_DRIVER, dev);//通知bus上所有设备bound消息  
  17. }  

到这里,设备就已经匹配成功了,这样就把设备和相应的驱动挂钩上了。
最后看一下他们的关系图:


原文:http://blog.csdn.net/new_abc/article/details/7582215
原创粉丝点击