Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1748567
  • 博文数量: 199
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 6186
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-30 11:01
个人简介

Linuxer.

文章存档

2015年(4)

2014年(28)

2013年(167)

分类: LINUX

2013-04-03 15:35:47


点击(此处)折叠或打开

  1. 二、linux设备模型层次关系:bus_type,device,device_driver

  2. 驱动核心可以注册多种类型的总线。
  3. 每种总线下面可以挂载许多设备。(通过kset devices)
  4. 每种总线下可以用很多设备驱动。(通过包含一个kset drivers)}
  5. 每个驱动可以处理一组设备。按照我的理解就是所有的设备都挂载到总线上,当加载驱动时,驱动就从总线上找到自己对应的设备。或者先把驱动加载上,来了一个设备就去总线找驱动。
  6. 这种基本关系的建立源于实际系统中各种总线,设备,驱动结构的抽象。

  7. 1.首先是总线,bus_type.
  8. struct bus_type {
  9.     const char *name;//总线名称
  10.     struct bus_attribute *bus_attrs//总线属性
  11.     struct device_attribute *dev_attrs;//设备属性
  12.     struct driver_attribute *drv_attrs;//驱动属性
  13.     int (*match)(struct device *dev, struct device_driver *drv);
  14.     int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
  15.     int (*probe)(struct device *dev);
  16.     int (*remove)(struct device *dev);
  17.     void (*shutdown)(struct device *dev);
  18.     int (*suspend)(struct device *dev, pm_message_t state);
  19.     int (*suspend_late)(struct device *dev, pm_message_t state);
  20.     int (*resume_early)(struct device *dev);
  21.     int (*resume)(struct device *dev);
  22.     struct dev_pm_ops *pm;
  23.     struct bus_type_private *p;
  24. };
  25. //bus_type的bus_type_private 成员
  26. struct bus_type_private {
  27.     struct kset subsys;
  28.     struct kset *drivers_kset;
  29.     struct kset *devices_kset;
  30.     struct klist klist_devices;
  31.     struct klist klist_drivers;
  32.     struct blocking_notifier_head bus_notifier;
  33.     unsigned int drivers_autoprobe:1;
  34.     struct bus_type *bus;
  35. };
  36. (1)总线的删除
  37. void bus_unregister(struct bus_type *bus);
  38. (2)总线的match方法
  39. int (*match)(struct device *dev, struct device_driver *drv);
  40. //当一个新设备或者驱动被添加到这个总线时,该方法被调用,用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非0值。下面的测试程序采用匹配设备的dev->bus_id字符串和驱动的drv->name字符串是否相同来判断驱动是否能处理该设备。
  41. (3)总线uevent方法
  42. int (*uevent)(structdevice *dev, char **envp, int num_envp)//在为用户产生热插拔事件之前,这个方法允许总线添加环境变量。
  43. (4)总线属性由结构bus_attribute描述:
  44. struct bus_attribute {
  45.     struct attribute attr;
  46.     ssize_t (*show)(struct bus_type *bus,char *buf);
  47.     ssize_t (*store)(struct bus_type *bus,const char *buf, size_t count);
  48. };
  49. BUS_ATTR(name,mode, show, store)//在编译时创建和初始化bus_attribute结构,它将bus_attr_作为给定前缀来创建总线的真正名称。
  50. 如:static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);//将创建一个bus_attr_version结构体对象。
  51. (5)创建\删除属性文件
  52. int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)
  53. void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr)
  54. (6)可以看出该结构体中包含了有device和dirver的kset对象。
  55. 总线的注册:int bus_register(structbus_type *bus);如果成功,新的总线将被添加到系统,在/sys/bus目录下可以看到。
  56. int bus_register(struct bus_type *bus)
  57. {
  58.     int retval;
  59.     struct bus_type_private *priv;
  60.     priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL); //分配空间
  61.     if (!priv)
  62.         return -ENOMEM;
  63.     priv->bus = bus;
  64.     bus->p = priv;//建立bus_type和bus_type_private的关系

  65.     BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
  66.     //设置总线子系统kobject的名称
  67.     retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);//给总线的kset结构里的kobject结构设置name,在/sys/bus目录下出现时就是这个bus名
  68.     if (retval)
  69.         goto out;
  70.     
  71.     priv->subsys.kobj.kset = bus_kset;//设置总线子系统kobject的所属集合,其实对应sys/bus/ 目录
  72.     priv->subsys.kobj.ktype = &bus_ktype;//kobj_type类型变量,和sysfs有关
  73.     priv->drivers_autoprobe = 1; //这个变量如果置位,则会执行一个函数,在驱动注册会看到它的运用
  74.     
  75.     //注册kset,就是建立/sys/bus/bus->name的目录
  76.     retval = kset_register(&priv->subsys);
  77.     if (retval)
  78.         goto out;
  79.     
  80.     //创建bus的属性文件
  81.     retval = bus_create_file(bus, &bus_attr_uevent);//调用sysfs_create_file(&bus->p->subsys.kobj, &attr->attr);
  82.     if (retval)
  83.         goto bus_uevent_fail;
  84.     
  85.     ///sys/bus/bus->name目录下创建devices目录,父目录就是priv->subsys.kobj,即/sys/bus/bus->name的目录
  86.     priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);
  87.     if (!priv->devices_kset) {
  88.         retval = -ENOMEM;
  89.         goto bus_devices_fail;
  90.     }
  91.     
  92.     ///sys/bus/bus->name目录下创建drivers目录,父目录就是priv->subsys.kobj,即/sys/bus/bus->name的目录
  93.     priv->drivers_kset = kset_create_and_add("drivers", NULL,&priv->subsys.kobj);
  94.     if (!priv->drivers_kset) {
  95.         retval = -ENOMEM;
  96.         goto bus_drivers_fail;
  97.     }
  98.     
  99.     // //初始化总线设备\总线驱动链表
  100.     klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
  101.     klist_init(&priv->klist_drivers, NULL, NULL);
  102.     
  103.     retval = add_probe_files(bus);//添加探测属性retval = bus_create_file(bus, &bus_attr_drivers_probe); retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);
  104.     if (retval)
  105.         goto bus_probe_files_fail;
  106.     
  107.     retval = bus_add_attrs(bus);// 添加其他属性,bus_create_file(bus, &bus->bus_attrs[i]);
  108.     if (retval)
  109.         goto bus_attrs_fail;
  110.     
  111.     pr_debug("bus: '%s': registered\n", bus->name);
  112.     return 0;
  113.     
  114. bus_attrs_fail:
  115.     remove_probe_files(bus);
  116. bus_probe_files_fail:
  117.     kset_unregister(bus->p->drivers_kset);
  118. bus_drivers_fail:
  119.     kset_unregister(bus->p->devices_kset);
  120. bus_devices_fail:
  121.     bus_remove_file(bus, &bus_attr_uevent);
  122. bus_uevent_fail:
  123.     kset_unregister(&bus->p->subsys);
  124.     kfree(bus->p);
  125. out:
  126.     return retval;
  127. }

  128. 2.下面是设备device的定义:
  129. struct device {
  130.     struct klist klist_children;
  131.     struct klist_nodeknode_parent;/* node in sibling list */
  132.     struct klist_nodeknode_driver;
  133.     struct klist_nodeknode_bus;
  134.     struct device *parent;//父设备,一般一个bus也对应一个设备。
  135.     struct kobject kobj; //代表自身
  136.     char bus_id[BUS_ID_SIZE];/* position on parent bus */
  137.     unsigned uevent_suppress:1;
  138.     const char *init_name; /*设备初始名 */
  139.     struct device_type*type;
  140.     struct semaphoresem;/* semaphore to synchronize calls to its driver. */
  141.     struct bus_type*bus;/* 所属的总线 */
  142.     struct device_driver *driver; /* 匹配的驱动*/
  143.     void *driver_data;/* data private to the driver */
  144.     void *platform_data;/* 由驱动定义并使用 */
  145.     struct dev_pm_infopower;
  146.     u64 *dma_mask;/* dma mask (if dma'able device) */
  147.     u64 coherent_dma_mask;
  148.     struct device_dma_parameters *dma_parms;
  149.     struct list_headdma_pools;/* dma pools (if dma'ble) */
  150.     struct dma_coherent_mem*dma_mem; /* internal for coherent mem override */
  151.     struct dev_archdataarchdata; /* arch specific additions */
  152.     dev_t devt;/* dev_t, creates the sysfs "dev" */
  153.     spinlock_t devres_lock;
  154.     struct list_headdevres_head;
  155.     struct klist_nodeknode_class;
  156.     struct class *class;
  157.     struct attribute_group**groups;/* optional groups */
  158.     void (*release)(struct device *dev);
  159. };

  160. //可以看出device结构体中也包含了一个kobject对象
  161. (1)注册设备
  162. int device_register(struct device *dev);
  163. (2)注销设备
  164. viod device_unregister(struct device *dev)
  165. (3)设备属性由struct device_attribute描述
  166. structdevice_attribute {
  167. struct attribute attr;
  168. ssize_t (*show)(struct device *dev,struct device_attribute *attr,char *buf);
  169. ssize_t (*store)(struct device *dev,struct device_attribute *attr,const char *buf, size_t count);
  170. };
  171. (4)创建属性文件
  172. int device_create_file(struct device *dev, struct device_attibute *entry)
  173. (5)删除属性文件
  174. void device_remove_file(struct device *dev, struct device_attibute *entry)
  175. (6)device_register代码
  176. int device_register(struct device *dev)
  177. {
  178.     device_initialize(dev);//初始化设备各个字段
  179.     return device_add(dev);
  180. }

  181. void device_initialize(struct device *dev)
  182. {
  183.  kobj_set_kset_s(dev, devices_subsys); //所有的dev属于devices_subsys这个集合
  184.  kobject_init(&dev->kobj); //初始kobj
  185.  klist_init(&dev->klist_children, klist_children_get,klist_children_put);//初始化子设备链表
  186.  INIT_LIST_HEAD(&dev->dma_pools);
  187.  INIT_LIST_HEAD(&dev->node);
  188.  init_MUTEX(&dev->sem);
  189.  device_init_wakeup(dev, 0);
  190. }
  191. int device_add(struct device *dev)
  192. {
  193.     struct device *parent = NULL;
  194.     struct kobject *kobj;
  195.     struct class_interface *class_intf;
  196.     int error = -EINVAL;
  197.     
  198.     dev = get_device(dev);//增加使用计数
  199.     if (!dev)
  200.         goto done;
  201.     
  202.     if (!dev->p) {
  203.         /*int device_private_init(struct device *dev)
  204.             {
  205.          dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL);
  206.          if (!dev->p)
  207.          return -ENOMEM;
  208.          dev->p->device = dev;//指向设备自己
  209.          klist_init(&dev->p->klist_children, klist_children_get,klist_children_put);//初始化设备私有成员的子设备链表,还有两个函数,关于增加和减少子设备引用计数的
  210.          return 0;
  211.         }
  212.         */
  213.         error = device_private_init(dev);
  214.         if (error)
  215.              goto done;
  216.     }
  217.     
  218.     if (dev->init_name) {//设备初始名存在
  219.         /*
  220.             int dev_set_name(struct device *dev, const char *fmt, ...)
  221.             {
  222.      va_list vargs;
  223.      int err;
  224.     
  225.      va_start(vargs, fmt);
  226.      err = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
  227.      va_end(vargs);
  228.      return err;
  229.              }
  230.         */
  231.         dev_set_name(dev, "%s", dev->init_name);//赋值给设备本身的kobject结构的name
  232.         dev->init_name = NULL;
  233.     }
  234.     
  235.     /*检查设备名是否存在,否则使用dev->bus->dev_name, dev->id生成设备本身的kobject结构的name*/
  236.     if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
  237.         dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
  238.     
  239.     if (!dev_name(dev)) {//再次检查name
  240.         error = -EINVAL;
  241.         goto name_error;
  242.     }
  243.     
  244.     pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
  245.     
  246.     parent = get_device(dev->parent);//增加父设备计数,并返回父设备结构
  247.     kobj = get_device_parent(dev, parent);//找到父设备对应的kobject结构
  248.     if (kobj)
  249.         dev->kobj.parent = kobj;//将本设备的kobj的parent字段指向父设备的kobject结构
  250.     
  251.     /* use parent numa_node */
  252.     if (parent)
  253.         set_dev_node(dev, dev_to_node(parent));// dev->numa_node = node;
  254.     
  255.     //将Kobject对象注册到linux系统,即在dev->kobj.parent的目录下创建前边设置过的name的本设备的目录
  256.     error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
  257.     if (error)
  258.         goto Error;
  259.     
  260.     /* notify platform of device entry */
  261.     if (platform_notify)
  262.         platform_notify(dev);
  263.     
  264.     //为sysfs文件系统创建设备的属性文件
  265.     error = device_create_file(dev, &uevent_attr);
  266.     if (error)
  267.     goto attrError;
  268.     
  269.     if (MAJOR(dev->devt)) {//如果存在设备号则添加dev_t属性,这样udev就能读取设备号属性从而在/dev/目录下创建设备节点,这样kobj和cdev也关联了
  270.         error = device_create_file(dev, &devt_attr);//创建属性文件static struct device_attribute devt_attr =__ATTR(dev, S_IRUGO, show_dev, NULL);
  271.         if (error)
  272.             goto ueventattrError;
  273.         
  274.         //创建一些符号链接
  275.         error = device_create_sys_dev_entry(dev);
  276.         if (error)
  277.             goto devtattrError;
  278.     
  279.         devtmpfs_create_node(dev);///dev下动态创建设备节点
  280.     }
  281.     
  282.     //建立类的sysfs符号连接
  283.     error = device_add_class_symlinks(dev);
  284.     if (error)
  285.         goto SymlinkError;
  286.     error = device_add_attrs(dev);//调用device_create_file(dev, &bus->dev_attrs[i])为sysfs文件系统创建属性文件
  287.     if (error)
  288.         goto AttrsError;
  289.     error = bus_add_device(dev);//创建bus的一些符号链接,将设备添加进总线中
  290.     if (error)
  291.         goto BusError;
  292.     error = dpm_sysfs_add(dev);//电源管理
  293.     if (error)
  294.         goto DPMError;
  295.     device_pm_add(dev);//电源管理
  296.     
  297.     if (dev->bus)//调用注册bus通知链上的所有函数
  298.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,BUS_NOTIFY_ADD_DEVICE, dev);
  299.     
  300.     //主要是向用户空间发送消息,实现热插拔
  301.     kobject_uevent(&dev->kobj, KOBJ_ADD);
  302.     bus_probe_device(dev); //现在该为设备在总线上寻找合适的驱动了
  303.     if (parent)//如果父设备存在
  304.         klist_add_tail(&dev->p->knode_parent,&parent->p->klist_children);//将子设备添加到父设备的链表中
  305.     
  306.     if (dev->class) {
  307.         mutex_lock(&dev->class->p->mutex);
  308.         klist_add_tail(&dev->knode_class,&dev->class->p->klist_devices);    /* tie the class to the device */
  309.     
  310.         /* notify any interfaces that the device is here */
  311.         list_for_each_entry(class_intf,&dev->class->p->interfaces, node)
  312.              if (class_intf->add_dev)
  313.                 class_intf->add_dev(dev, class_intf);
  314.         mutex_unlock(&dev->class->p->mutex);
  315.     }
  316.     done:
  317.     put_device(dev);
  318.     return error;
  319. .......//出错处理
  320. }

  321. int bus_add_device(struct device *dev)
  322. {
  323.     struct bus_type *bus = bus_get(dev->bus);
  324.     int error = 0;
  325.     
  326.     if (bus) {
  327.         pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
  328.         error = device_add_attrs(bus, dev);//创建属性文件
  329.         if (error)
  330.             goto out_put;
  331.         error = sysfs_create_link(&bus->p->devices_kset->kobj,&dev->kobj, dev_name(dev));//创建设备所在bus目录下的设备链接
  332.         if (error)
  333.             goto out_id;
  334.         error = sysfs_create_link(&dev->kobj,&dev->bus->p->subsys.kobj, "subsystem");//创建链接
  335.         if (error)
  336.             goto out_subsys;
  337.         klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);//将设备添加到所在bus总线下的链表中,将设备添加进总线的设备链表
  338.     }
  339.     return 0;
  340.     
  341. out_subsys:
  342.     sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
  343. out_id:
  344.     device_remove_attrs(bus, dev);
  345. out_put:
  346.     bus_put(dev->bus);
  347.     return error;
  348. }

  349. void bus_probe_device(struct device *dev)
  350. {
  351.     struct bus_type *bus = dev->bus;//找到设备所在的总线
  352.     int ret;
  353.     
  354.     if (bus && bus->p->drivers_autoprobe) {//drivers_autoprobe标志设为1,表明要自动匹配驱动
  355.         ret = device_attach(dev); //为设备寻找驱动
  356.         WARN_ON(ret < 0);
  357.     }
  358. }

  359. int device_attach(struct device *dev)
  360. {
  361.     int ret = 0;

  362.     device_lock(dev);//锁住设备
  363.     if (dev->driver) {//如果设备有驱动
  364.         ret = device_bind_driver(dev);//那么将设备和驱动绑定
  365.         if (ret == 0)
  366.             ret = 1;
  367.         else {
  368.             dev->driver = NULL;
  369.             ret = 0;
  370.         }
  371.     } else {//如果设备没有驱动
  372.         pm_runtime_get_noresume(dev);
  373.         ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); //在总线上寻找驱动与该设备进行匹配
  374.         pm_runtime_put_sync(dev);
  375.     }
  376.     device_unlock(dev);
  377.     return ret;
  378. }

  379. int device_bind_driver(struct device *dev)
  380. {
  381.     int ret;

  382.     ret = driver_sysfs_add(dev);//主要是添加driver和dev之间的连接文件
  383.     if (!ret)
  384.         driver_bound(dev);//驱动绑定设备
  385.     return ret;
  386. }

  387. static int driver_sysfs_add(struct device *dev)
  388. {
  389.     int ret;
  390.         //1:在驱动目录下建立一个到设备的同名链接
  391.         //2:在设备目录下建立一个名为driver。到驱动的链接
  392.     ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,kobject_name(&dev->kobj)); //在driver目录下添加以dev->kobj名字的连接文件,连接到device
  393.     if (ret == 0) {
  394.         ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,"driver"); //同样在device目录下添加‘driver’为名字的连接文件连接到drvier
  395.         if (ret)
  396.             sysfs_remove_link(&dev->driver->p->kobj,kobject_name(&dev->kobj));
  397.     }
  398.     return ret;
  399. }

  400. static void driver_bound(struct device *dev)
  401. {
  402.     if (klist_node_attached(&dev->p->knode_driver)) {
  403.         printk(KERN_WARNING "%s: device %s already bound\n",__func__, kobject_name(&dev->kobj));
  404.         return;
  405.     }
  406.     
  407.     pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),__func__, dev->driver->name);
  408.     
  409.     //实现将驱动程序和设备联系起来。
  410.     klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
  411.     
  412.     if (dev->bus)//调用注册bus通知链上的所有函数
  413.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,BUS_NOTIFY_BOUND_DRIVER, dev);
  414. }

  415. int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,void *data, int (*fn)(struct device_driver *, void *))
  416. {
  417.     struct klist_iter i;
  418.     struct device_driver *drv;
  419.     int error = 0;

  420.     if (!bus)
  421.         return -EINVAL;

  422.     klist_iter_init_node(&bus->p->klist_drivers, &i,start ? &start->p->knode_bus : NULL); //初始化i结构体
  423.     while ((drv = next_driver(&i)) && !error)//遍历总线上的驱动
  424.         error = fn(drv, data);//将驱动和设备进行匹配,这里的fn=__device_attach
  425.     klist_iter_exit(&i);
  426.     return error;
  427. }


  428. static int __device_attach(struct device_driver *drv, void *data)
  429. {
  430.     struct device *dev = data;

  431.     if (!driver_match_device(drv, dev))//现用总线上的match匹配函数进行低级匹配
  432.         return 0;

  433.     return driver_probe_device(drv, dev); //再来高级匹配
  434. }

  435.  
  436. static inline int driver_match_device(struct device_driver *drv, struct device *dev)
  437. {
  438.     return drv->bus->match ? drv->bus->match(dev, drv) : 1;//看到没,这里要调用总线上定义的match函数,实际就是比较设备名和驱动名是否一样
  439. }

  440. int driver_probe_device(struct device_driver *drv, struct device *dev)
  441. {
  442.     int ret = 0;

  443.     if (!device_is_registered(dev)) //设备是否注册,返回 return dev->kobj.state_in_sysfs
  444.         return -ENODEV;

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

  446.     pm_runtime_get_noresume(dev);
  447.     pm_runtime_barrier(dev);
  448.     ret = really_probe(dev, drv);//调用真正的匹配
  449.     pm_runtime_put_sync(dev);

  450.     return ret;
  451. }

  452. static int really_probe(struct device *dev, struct device_driver *drv)
  453. {
  454.     int ret = 0;

  455.     atomic_inc(&probe_count);
  456.     pr_debug("bus: '%s': %s: probing driver %s with device %s/n",drv->bus->name, __func__, drv->name, dev_name(dev));
  457.     WARN_ON(!list_empty(&dev->devres_head));

  458.     dev->driver = drv;
  459.     if (driver_sysfs_add(dev)) {//主要是添加driver和dev之间的连接文件,见上
  460.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed/n",__func__, dev_name(dev));
  461.         goto probe_failed;
  462.     }

  463.     if (dev->bus->probe) {//现用总线上定义的probe函数尝试一下
  464.         ret = dev->bus->probe(dev);
  465.         if (ret)
  466.             goto probe_failed;
  467.     } else if (drv->probe) {//如果不行,在用驱动上的probe尝试
  468.         ret = drv->probe(dev);
  469.         if (ret)
  470.             goto probe_failed;
  471.     }

  472.     driver_bound(dev);//驱动绑定设备
  473.     ret = 1;
  474.     pr_debug("bus: '%s': %s: bound device %s to driver %s/n",drv->bus->name, __func__, dev_name(dev), drv->name);
  475.     goto done;

  476. probe_failed:
  477.     devres_release_all(dev);
  478.     driver_sysfs_remove(dev);
  479.     dev->driver = NULL;

  480.     if (ret != -ENODEV && ret != -ENXIO) {/* driver matched but the probe failed */
  481.         printk(KERN_WARNING"%s: probe of %s failed with error %d/n",drv->name, dev_name(dev), ret);
  482.     }

  483.     ret = 0;
  484. done:
  485.     atomic_dec(&probe_count);
  486.     wake_up(&probe_waitqueue);
  487.     return ret;
  488. }

  489. 3.下面是设备驱动定义:
  490. struct device_driver {
  491.     const char *name;//驱动名称
  492.     struct bus_type*bus; //所在总线
  493.     struct module *owner;
  494.     const char *mod_name;/* used for built-in modules */
  495.     int (*probe) (struct device *dev);
  496.     int (*remove) (struct device *dev);
  497.     void (*shutdown) (struct device *dev);
  498.     int (*suspend) (struct device *dev, pm_message_t state);
  499.     int (*resume) (struct device *dev);
  500.     struct attribute_group **groups;
  501.     struct dev_pm_ops *pm;
  502.     struct driver_private *p; //
  503. };

  504. struct driver_private {
  505.     struct kobject kobj;//代表自身
  506.     struct klist klist_devices;//设备列表
  507.     struct klist_node knode_bus;
  508.     struct module_kobject *mkobj;
  509.     struct device_driver *driver;
  510. };

  511. (1)当总线的match返回非0值,也就是总线找到与驱动相匹配的设备时,驱动的probe的函数将被调用。
  512. (2)当设备从系统总删除是remove被调用。
  513. (3)当系统关机的时候shutdown被调用。
  514. (4)创建属性文件
  515. int dirver_create_file(struct device_driver *drv, struct driver_attribute *attr);
  516. (5)删除属性文件
  517. void driver_remove_file struct device_driver *drv, struct driver_attribute *attr);
  518. (6)驱动的属性使用structdriver_attribute来描述
  519.  structdriver_attribute{
  520.    structattribue attr;
  521.    ssize_t(*show)(struct device_driver *drv, const char *buf);
  522.    ssize_t(*store)(struct device_driver *drv, const char *buf, size_t count);
  523.  }
  524. (7)卸载总线上注销驱动
  525. int driver_register(structdevice_driver *drv)
  526. (8)在总线上注册驱动
  527. void driver_unregister(struct device_driver *drv)
  528. (9)代码分析
  529. int driver_register(struct device_driver *drv)
  530. {
  531.     int ret;
  532.     struct device_driver *other;

  533.     BUG_ON(!drv->bus->p); //判断bus->p是否为空

  534.     if ((drv->bus->probe && drv->probe) || //判断驱动跟驱动的总线是否有冲突的函数注册,给出警告信息
  535.         (drv->bus->remove && drv->remove) ||
  536.         (drv->bus->shutdown && drv->shutdown))
  537.         printk(KERN_WARNING "Driver '%s' needs updating - please use ""bus_type methods\n", drv->name);

  538.     other = driver_find(drv->name, drv->bus); //在注册在bus上的driver寻找是否有跟要注册的driver相同,有则表明驱动已被注册过
  539.     if (other) {
  540.         put_driver(other);
  541.         printk(KERN_ERR "Error: Driver '%s' is already registered, ""aborting...\n", drv->name);
  542.         return -EBUSY;
  543.     }

  544.     ret = bus_add_driver(drv); //经过上面的验证后,将驱动添加注册到bus上
  545.     if (ret)
  546.         return ret;
  547.     ret = driver_add_groups(drv, drv->groups); //如果grop不为空的话,将在驱动文件夹下创建以group名字的子文件夹,然后在子文件夹下添加group的属性文件
  548.     if (ret)
  549.         bus_remove_driver(drv);
  550.     return ret;
  551. }
  552.          
  553. int bus_add_driver(struct device_driver *drv)
  554. {
  555.     struct bus_type *bus;
  556.     struct driver_private *priv;
  557.     int error = 0;

  558.     bus = bus_get(drv->bus);//找到该drv所属的bus,其实就是增加该bus->p->subsys->kobject->kref的引用计数
  559.     if (!bus)
  560.         return -EINVAL;

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

  562.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);//分配driver_private结构
  563.     if (!priv) {
  564.         error = -ENOMEM;
  565.         goto out_put_bus;
  566.     }
  567.     klist_init(&priv->klist_devices, NULL, NULL);//初始化priv->klist_devices
  568.     priv->driver = drv; //将该drv赋值给priv->driver
  569.     drv->p = priv; //而drv的drv->p又等于priv
  570.     priv->kobj.kset = bus->p->drivers_kset; //指向bus的drvier容器
  571.     //在sysfs文件系统下在总线所在的drivers_kset目录下添加该驱动的目录
  572.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,"%s", drv->name); //驱动的kobject初始化和添加dir到sysfs中
  573.     if (error)
  574.         goto out_unregister;

  575.     if (drv->bus->p->drivers_autoprobe) { //这个变量默认是为1的
  576.         error = driver_attach(drv); //匹配相应的设备
  577.         if (error)
  578.             goto out_unregister;
  579.     }
  580.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); //将priv->knode_bus添加到bus->p->klist_drivers,即添加到总线上
  581.     module_add_driver(drv->owner, drv); //添加drv的module

  582.     error = driver_create_file(drv, &driver_attr_uevent); //在sysfs的目录下创建文件uevent属性文件
  583.     if (error) {
  584.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",__func__, drv->name);
  585.     }
  586.     error = driver_add_attrs(bus, drv);//给driver添加bus上的所有属性
  587.     if (error) {
  588.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",__func__, drv->name);
  589.     }
  590.     error = add_bind_files(drv); //添加绑定文件,driver_attr_bind 和 driver_attr_unbind
  591.     if (error) {
  592.         printk(KERN_ERR "%s: add_bind_files(%s) failed\n", __func__, drv->name);
  593.     }

  594.     kobject_uevent(&priv->kobj, KOBJ_ADD); //产生一个KOBJ_ADD uevent
  595.     return 0;
  596. out_unregister:
  597.     kfree(drv->p);
  598.     drv->p = NULL;
  599.     kobject_put(&priv->kobj);
  600. out_put_bus:
  601.     bus_put(bus);
  602.     return error;
  603. }
  604.          
  605. int driver_attach(struct device_driver *drv)
  606. {
  607.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
  608. }

  609. //该函数将调用bus_for_each_dev()
  610. int bus_for_each_dev(struct bus_type *bus, struct device *start,void *data, int (*fn)(struct device *, void *))
  611. {
  612.     struct klist_iter i;
  613.     struct device *dev;
  614.     int error = 0;

  615.     if (!bus)
  616.         return -EINVAL;

  617.     klist_iter_init_node(&bus->p->klist_devices, &i,(start ? &start->p->knode_bus : NULL)); //将bus中的已注册的device列表放到迭代器中,方便索引
  618.     while ((dev = next_device(&i)) && !error) //将驱动逐个地与列表中每一个的device匹配,可能一个驱动匹配好几个设备
  619.         error = fn(dev, data); //这个fn就是上面传下来的__driver_attach
  620.     klist_iter_exit(&i);
  621.     return error;
  622. }

  623. static int __driver_attach(struct device *dev, void *data)
  624. {
  625.     struct device_driver *drv = data;
  626.     if (!driver_match_device(drv, dev)) //跟名字的意思一样,driver跟device尝试匹配
  627.         return 0;

  628.     if (dev->parent) /* Needed for USB */
  629.         down(&dev->parent->sem);
  630.     down(&dev->sem);
  631.     if (!dev->driver)
  632.         driver_probe_device(drv, dev);//再来高级匹配
  633.     up(&dev->sem);
  634.     if (dev->parent)
  635.         up(&dev->parent->sem);

  636.     return 0;
  637. }

  638. static inline int driver_match_device(struct device_driver *drv,struct device *dev)
  639. {
  640.     return drv->bus->match ? drv->bus->match(dev, drv) : 1;//调用总线的match函数
  641. }
  642.  
  643. int driver_probe_device(struct device_driver *drv, struct device *dev)
  644. {
  645.     int ret = 0;

  646.     if (!device_is_registered(dev)) //首先判断这个device是否已经注册
  647.         return -ENODEV;

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

  649.     ret = really_probe(dev, drv); //转而调用really_probe(),同以上的device_register()里调用的

  650.     return ret;
  651. }

  652. void module_add_driver(struct module *mod, struct device_driver *drv)
  653. {
  654.     char *driver_name;
  655.     int no_warn;
  656.     struct module_kobject *mk = NULL;

  657.     if (!drv)
  658.         return;

  659.     if (mod)//一般情况下为THIS_MODULE
  660.         mk = &mod->mkobj;
  661.     else if (drv->mod_name) {//如果没模块,则检查驱动的模块名
  662.         struct kobject *mkobj;
  663.         mkobj = kset_find_obj(module_kset, drv->mod_name); //根据驱动模块的名字去module_kset集合中找
  664.         if (mkobj) {
  665.             mk = container_of(mkobj, struct module_kobject, kobj); //用container_of方法通过kobj转换成module_kobject
  666.             drv->p->mkobj = mk; //赋值给驱动的mkobj
  667.             kobject_put(mkobj);
  668.         }
  669.     }

  670.     if (!mk) //mk如果为null则返回
  671.         return;

  672.     no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module"); //在驱动文件夹下创建名为‘module’的链接文件,链接到module文件夹
  673.     driver_name = make_driver_name(drv); //生成driver_name,给module用
  674.     if (driver_name) {
  675.         module_create_drivers_dir(mk); //在具体的module文件夹下创建driver目录
  676.         no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj,make_driver_name()); //在上面创建的driver目录下,生成一个名为driver_name指定的链接文件,链接到驱动的文件夹
  677.         kfree(driver_name);
  678.     }
  679. }
  680. 总体来说,驱动的注册比较复杂,但是我们可以简单概况一下。
  681. 1、在总线上找找该驱动有没有被注册过
  682. 2、若没有注册过,则将驱动加入到总线驱动集合中
  683. 3、在总线上找能匹配驱动的设备
  684.      1、将总线上每个设备进行匹配
  685.      2、首先用总线的match 函数进行低级匹配
  686.      3、然后在用总线的probe函数进行高级匹配,若失败,则用驱动上的probe寒酸进行高级匹配
  687.      4、如果匹配成功,则将设备绑定到驱动链表中
  688. 4、如果匹配成功,则将驱动加入到总线的驱动链表中

  689. 4、结束语
  690. 系统初始化时,会扫描连接那些设备,并为扫描到的设备建立一个struct device的变量,接下来就是驱动,每次扫描有一个驱动程序,就要为其分配一个struct device_driver结构变量,并把这些变量加入相应的链表中,device插入devices、driver插入drivers中去,这样总线伤的两条链表变这样诞生了。在以前的系统中都是先有设备后又驱动的,因为设备都是先插好了再商店开机的。这样devices链表会先被创建,而后就是drivers链表,然后驱动程序就开始初始化,开始注册其struct devicr_driver结构,然后他就去总线的devices链表中去寻找(遍历)还没有绑定driver的设备,即struct device中的struct device_driver指针乃为空的设备。然后去观察该设备的特征,若匹配就会调用device_bind_driver的函数结合在一起,换句话说,把struct device中的struct devicr_drive driver指向这个driver,而struct device_driver drivers加入他的那张struct klist *klist_devices链表中来,这样 bus、device、driver就建立起关系并联系起来了。

三、测试模块


         1.BUS

[html] view plaincopy
  1. #include <linux/device.h>  
  2. #include <linux/module.h>  
  3. #include <linux/kernel.h>  
  4. #include <linux/init.h>  
  5. #include <linux/string.h>  
  6.   
  7. MODULE_AUTHOR("David Xie");  
  8. MODULE_LICENSE("Dual BSD/GPL");  
  9.   
  10. static char *Version = "$Revision: 1.9 {1}quot;;  
  11.   
  12. static int my_match(struct device *dev, struct device_driver *driver)  
  13. {  
  14.     return !strncmp(dev->bus_id, driver->name, strlen(driver->name));  
  15. }  
  16.   
  17. static void my_bus_release(struct device *dev)  
  18. {  
  19.     printk(KERN_DEBUG "my bus release\n");  
  20. }  
  21.       
  22. struct device my_bus = {  
  23.     .bus_id   = "my_bus0",  
  24.     .release  = my_bus_release  
  25. };  
  26.   
  27.   
  28. struct bus_type my_bus_type = {  
  29.     .name = "my_bus",  
  30.     .match = my_match,  
  31. };  
  32.   
  33. EXPORT_SYMBOL(my_bus);  
  34. EXPORT_SYMBOL(my_bus_type);  
  35.   
  36.   
  37. /*  
  38.  * Export a simple attribute.  
  39.  */  
  40. static ssize_t show_bus_version(struct bus_type *bus, char *buf)  
  41. {  
  42.     return snprintf(buf, PAGE_SIZE, "%s\n", Version);  
  43. }  
  44.   
  45. static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);  
  46.   
  47.   
  48. static int __init my_bus_init(void)  
  49. {  
  50.     int ret;  
  51.           
  52.         /*注册总线*/  
  53.     ret = bus_register(&my_bus_type);  
  54.     if (ret)  
  55.         return ret;  
  56.           
  57.     /*创建属性文件*/    
  58.     if (bus_create_file(&my_bus_type, &bus_attr_version))  
  59.         printk(KERN_NOTICE "Fail to create version attribute!\n");  
  60.       
  61.     /*注册总线设备*/  
  62.     ret = device_register(&my_bus);  
  63.     if (ret)  
  64.         printk(KERN_NOTICE "Fail to register device:my_bus!\n");  
  65.           
  66.     return ret;  
  67. }  
  68.   
  69. static void my_bus_exit(void)  
  70. {  
  71.     device_unregister(&my_bus);  
  72.     bus_unregister(&my_bus_type);  
  73. }  
  74.   
  75. module_init(my_bus_init);  
  76. module_exit(my_bus_exit);  

创建一条名为my_bus_type的总线和一个名为my_bus的总线设备,注意总线也是一个设备,也需要注册。

测试结果:




2.DEVICE

[html] view plaincopy
  1. #include <linux/device.h>  
  2. #include <linux/module.h>  
  3. #include <linux/kernel.h>  
  4. #include <linux/init.h>  
  5. #include <linux/string.h>  
  6.   
  7. MODULE_AUTHOR("David Xie");  
  8. MODULE_LICENSE("Dual BSD/GPL");  
  9.   
  10. extern struct device my_bus;   
  11. extern struct bus_type my_bus_type;  
  12.   
  13. /* Why need this ?*/  
  14. static void my_dev_release(struct device *dev)  
  15. {   
  16.       
  17. }  
  18.   
  19. struct device my_dev = {  
  20.     .bus = &my_bus_type,  
  21.     .parent = &my_bus,  
  22.     .release = my_dev_release,  
  23. };  
  24.   
  25. /*  
  26.  * Export a simple attribute.  
  27.  */  
  28. static ssize_t mydev_show(struct device *dev, char *buf)  
  29. {  
  30.     return sprintf(buf, "%s\n", "This is my device!");  
  31. }  
  32.   
  33. static DEVICE_ATTR(dev, S_IRUGO, mydev_show, NULL);  
  34.   
  35. static int __init my_device_init(void)  
  36. {  
  37.     int ret = 0;  
  38.           
  39.         /* 初始化设备 */  
  40.     strncpy(my_dev.bus_id, "my_dev", BUS_ID_SIZE);  
  41.           
  42.         /*注册设备*/  
  43.     device_register(&my_dev);  
  44.           
  45.     /*创建属性文件*/  
  46.     device_create_file(&my_dev, &dev_attr_dev);  
  47.       
  48.     return ret;   
  49.   
  50. }  
  51.   
  52. static void my_device_exit(void)  
  53. {  
  54.     device_unregister(&my_dev);  
  55. }  
  56.   
  57. module_init(my_device_init);  
  58. module_exit(my_device_exit);  

注册一个bus_id即名字为my_dev的设备,该设备的bus成员指向上一步创建的my_bus_type总线,parent成员指向上一步创建的my_bus总线设备。

         测试结果:



3.DRIVER

[html] view plaincopy
  1. #include <linux/device.h>  
  2. #include <linux/module.h>  
  3. #include <linux/kernel.h>  
  4. #include <linux/init.h>  
  5. #include <linux/string.h>  
  6.   
  7. MODULE_AUTHOR("David Xie");  
  8. MODULE_LICENSE("Dual BSD/GPL");  
  9.   
  10. extern struct bus_type my_bus_type;  
  11.   
  12. static int my_probe(struct device *dev)  
  13. {  
  14.     printk("Driver found device which my driver can handle!\n");  
  15.     return 0;  
  16. }  
  17.   
  18. static int my_remove(struct device *dev)  
  19. {  
  20.     printk("Driver found device unpluged!\n");  
  21.     return 0;  
  22. }  
  23.   
  24. struct device_driver my_driver = {  
  25.     .name = "my_dev",  
  26.     .bus = &my_bus_type,  
  27.     .probe = my_probe,  
  28.         .remove = my_remove,  
  29. };  
  30.   
  31. /*  
  32.  * Export a simple attribute.  
  33.  */  
  34. static ssize_t mydriver_show(struct device_driver *driver, char *buf)  
  35. {  
  36.     return sprintf(buf, "%s\n", "This is my driver!");  
  37. }  
  38.   
  39. static DRIVER_ATTR(drv, S_IRUGO, mydriver_show, NULL);  
  40.   
  41. static int __init my_driver_init(void)  
  42. {  
  43.     int ret = 0;  
  44.           
  45.         /*注册驱动*/  
  46.     driver_register(&my_driver);  
  47.           
  48.     /*创建属性文件*/  
  49.     driver_create_file(&my_driver, &driver_attr_drv);  
  50.       
  51.     return ret;   
  52.   
  53. }  
  54.   
  55. static void my_driver_exit(void)  
  56. {  
  57.     driver_unregister(&my_driver);  
  58. }  
  59.   
  60. module_init(my_driver_init);  
  61. module_exit(my_driver_exit);  

创建一个名为“bus_dev”的驱动,并将bus成员指向第一步创建的my_bus_type总线


阅读(2850) | 评论(0) | 转发(4) |
1

上一篇:linux 设备模型(1)

下一篇:sysfs文件系统

给主人留下些什么吧!~~