终于说到最后一个注册了,今天也是年末了,可是我依然战斗在一线的感觉!说完这个,我也得放松一会儿。学习内核也接近大半个月了,收获颇多,不过还有太多东西需要我在继续努力了,虽然博客的流量不是很理想,表明关注我博客的网友不是很多,但是我相信,就会在不久,linux成为千家万户都在关注的对象时,我博客将成为初学者很好的入门资料,这也是我写这些文章的一个出发点,希望以后在来回味自己走过linux的路程时有所感慨!来自:drivers/base/driver.c:int driver_register(struct device_driver *drv){ int ret; struct device_driver *other; BUG_ON(!drv->bus->p); if ((drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)) printk(KERN_WARNING "Driver '%s' needs updating - please use " "bus_type methods/n", drv->name); other = driver_find(drv->name, drv->bus); //比较好理解的函数,也就是在总线中找到和该驱动同名的驱动//说白了,就是看看这个驱动之前注册过没 if (other) { put_driver(other); //如果注册过,那么我们将不再注册,注意减少驱动引用,因为在driver_find中增加过 printk(KERN_ERR "Error: Driver '%s' is already registered, " "aborting.../n", drv->name); return -EBUSY; } ret = bus_add_driver(drv); //如果没有注册过,那么我们将该驱动加入总线中 if (ret) return ret; ret = driver_add_groups(drv, drv->groups); if (ret) bus_remove_driver(drv); return ret;}struct device_driver *driver_find(const char *name, struct bus_type *bus){ struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); //这个函数顾名思义,就是在总线集合中找到名称为name的kobject对象,其实就是驱动名称了 struct driver_private *priv; if (k) { //如果找到了 priv = to_driver(k); return priv->driver; //返回驱动指针 } return NULL;}int bus_add_driver(struct device_driver *drv){ struct bus_type *bus; struct driver_private *priv; int error = 0; bus = bus_get(drv->bus); if (!bus) return -EINVAL; pr_debug("bus: '%s': add driver %s/n", bus->name, drv->name); priv = kzalloc(sizeof(*priv), GFP_KERNEL); //为驱动私有成员申请内存且清0 if (!priv) { error = -ENOMEM; goto out_put_bus; } klist_init(&priv->klist_devices, NULL, NULL); //初始化驱动所支持的设备链表 priv->driver = drv; drv->p = priv; priv->kobj.kset = bus->p->drivers_kset; //设置驱动kobject所属集合,显然这里就是对于总线的驱动集合 error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, "%s", drv->name); //初始化并添加驱动kobject对象到总线驱动中 if (error) goto out_unregister; if (drv->bus->p->drivers_autoprobe) { //还记得我说过这个变量, error = driver_attach(drv); //如果需要自动的去匹配,那么调用驱动匹配函数 if (error) goto out_unregister; } klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); //将驱动节点加入到总线链表中 module_add_driver(drv->owner, drv); error = driver_create_file(drv, &driver_attr_uevent); if (error) { printk(KERN_ERR "%s: uevent attr (%s) failed/n", __func__, drv->name); } error = driver_add_attrs(bus, drv); if (error) { /* How the hell do we get out of this pickle? Give up */ printk(KERN_ERR "%s: driver_add_attrs(%s) failed/n", __func__, drv->name); } if (!drv->suppress_bind_attrs) { error = add_bind_files(drv); if (error) { /* Ditto */ printk(KERN_ERR "%s: add_bind_files(%s) failed/n", __func__, drv->name); } } kobject_uevent(&priv->kobj, KOBJ_ADD); return 0;out_unregister: kobject_put(&priv->kobj); kfree(drv->p); drv->p = NULL;out_put_bus: bus_put(bus); return error;}来自base/dd.c:int driver_attach(struct device_driver *drv){ return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);}来自base/bus.c:int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *, void *)){ struct klist_iter i; struct device *dev; int error = 0; if (!bus) return -EINVAL; klist_iter_init_node(&bus->p->klist_devices, &i, (start ? &start->p->knode_bus : NULL)); //初始化i结构体,我们可以进去看看 while ((dev = next_device(&i)) && !error) //在总线的设备链表中遍历链表 error = fn(dev, data); //然后将设备和驱动进行匹配,这个fn=__driver_attch klist_iter_exit(&i); //清除i结构体 return error;}struct klist_iter { struct klist *i_klist; //所属链表 struct klist_node *i_cur; //链表中的节点};void klist_iter_init_node(struct klist *k, struct klist_iter *i, struct klist_node *n){ i->i_klist = k; i->i_cur = n; //这里的n为NULL if (n) kref_get(&n->n_ref);}static struct device *next_device(struct klist_iter *i){ struct klist_node *n = klist_next(i); //以i->i_cur节点为起点,得到链表i->i_klist的下一个节点 struct device *dev = NULL; struct device_private *dev_prv; if (n) { //如果有,返回该设备 dev_prv = to_device_private_bus(n); dev = dev_prv->device; } return dev;}struct klist_node *klist_next(struct klist_iter *i){ void (*put)(struct klist_node *) = i->i_klist->put; struct klist_node *last = i->i_cur; struct klist_node *next; spin_lock(&i->i_klist->k_lock); if (last) { //这里的last为空 next = to_klist_node(last->n_node.next); if (!klist_dec_and_del(last)) put = NULL; } else next = to_klist_node(i->i_klist->k_list.next); //得到链表的第一个节点 i->i_cur = NULL; while (next != to_klist_node(&i->i_klist->k_list)) { //遍历链表,如果没有到头 if (likely(!knode_dead(next))) { //如果发现节点next为有效节点 kref_get(&next->n_ref); //增加节点引用 i->i_cur = next; //将i结构的起始节点设为next break; } next = to_klist_node(next->n_node.next); //继续遍历链表中下一个节点 } spin_unlock(&i->i_klist->k_lock); if (put && last) put(last); return i->i_cur;}static int __driver_attach(struct device *dev, void *data){ struct device_driver *drv = data; /* * Lock device and try to bind to it. We drop the error * here and always return 0, because we need to keep trying * to bind to devices and some drivers will return an error * simply if it didn't support the device. * * driver_probe_device() will spit a warning if there * is an error. */ if (!driver_match_device(drv, dev)) //将驱动和设备匹配,如果成功返回0 return 0;//总线去匹配没有成功不要紧,因为,它只是一个很低级的匹配函数,我们还有更高级的 if (dev->parent) /* Needed for USB */ device_lock(dev->parent); device_lock(dev); if (!dev->driver) driver_probe_device(drv, dev); //驱动去匹配设备的高级匹配函数 device_unlock(dev); if (dev->parent) device_unlock(dev->parent); return 0;}static inline int driver_match_device(struct device_driver *drv, struct device *dev){ return drv->bus->match ? drv->bus->match(dev, drv) : 1; //这里就要用到总线的match函数了,所有的匹配都是通过它来的}int driver_probe_device(struct device_driver *drv, struct device *dev){ int ret = 0; if (!device_is_registered(dev)) //设备是否注册过,显然这里肯定注册过 return -ENODEV; pr_debug("bus: '%s': %s: matched device %s with driver %s/n", drv->bus->name, __func__, dev_name(dev), drv->name); pm_runtime_get_noresume(dev); //pm_xxx电源管理类 pm_runtime_barrier(dev); ret = really_probe(dev, drv); //真正执行的寒酸 pm_runtime_put_sync(dev); return ret;}static int really_probe(struct device *dev, struct device_driver *drv){ int ret = 0; atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s/n", drv->bus->name, __func__, drv->name, dev_name(dev)); WARN_ON(!list_empty(&dev->devres_head)); dev->driver = drv; if (driver_sysfs_add(dev)) { printk(KERN_ERR "%s: driver_sysfs_add(%s) failed/n", __func__, dev_name(dev)); goto probe_failed; } if (dev->bus->probe) { //如果总线的probe函数存在就用总线的 ret = dev->bus->probe(dev); if (ret) goto probe_failed; } else if (drv->probe) { //总线不存在,则看驱动的probe寒酸 ret = drv->probe(dev); if (ret) goto probe_failed; } driver_bound(dev); //将设备绑定到驱动上 ret = 1; pr_debug("bus: '%s': %s: bound device %s to driver %s/n", drv->bus->name, __func__, dev_name(dev), drv->name); goto done;probe_failed: devres_release_all(dev); driver_sysfs_remove(dev); dev->driver = NULL; if (ret != -ENODEV && ret != -ENXIO) { /* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d/n", drv->name, dev_name(dev), ret); } /* * Ignore errors returned by ->probe so that the next driver can try * its luck. */ ret = 0;done: atomic_dec(&probe_count); wake_up(&probe_waitqueue); return ret;}static void driver_bound(struct device *dev){ if (klist_node_attached(&dev->p->knode_driver)) { //如果设备已经绑定到了一个驱动,则返回 printk(KERN_WARNING "%s: device %s already bound/n", __func__, kobject_name(&dev->kobj)); return; } pr_debug("driver: '%s': %s: bound to device '%s'/n", dev_name(dev), __func__, dev->driver->name); klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); //将设备节点加入到该设备对应的驱动链表中 if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_BOUND_DRIVER, dev);}总体来说,驱动的注册比较复杂,但是我们可以简单概况一下。1、在总线上找找该驱动有没有被注册过2、若没有注册过,则将驱动加入到总线驱动集合中3、在总线上找能匹配驱动的设备 1、将总线上每个设备进行匹配 2、首先用总线的match 函数进行低级匹配 3、然后在用总线的probe函数进行高级匹配,若失败,则用驱动上的probe寒酸进行高级匹配 4、如果匹配成功,则将设备绑定到驱动链表中4、如果匹配成功,则将驱动加入到总线的驱动链表中好不容易啊,我们终于将3大注册函数说完,很兴奋,下一步做什么呢?其实我也不知道,继续探索吧... ....