linux设备模型之bus,device,driver分析二
2011-05-17 16:40
676 查看
===============================
本文系本站原创,欢迎转载!
转载请注明出处:http://blog.csdn.net/gdt_a20
===============================
上篇分析了bus,driver的注册过程,这篇主要分析device的注册,并总结给出个流程图。
三、device的注册
还是照例先看一下device的结构:
接下来详细看一下device的注册device_register:
以上便是device的注册,可以发现device和driver围绕着bus最后有种殊途同归的感觉,下面结合driver的流程给出一个框图
以便更明确其间的流程:
本文系本站原创,欢迎转载!
转载请注明出处:http://blog.csdn.net/gdt_a20
===============================
上篇分析了bus,driver的注册过程,这篇主要分析device的注册,并总结给出个流程图。
三、device的注册
还是照例先看一下device的结构:
struct device { struct device *parent; struct device_private *p; //私有属性结构,重点 struct kobject kobj; const char *init_name; /* initial name of the device */ struct device_type *type; struct mutex mutex; /* mutex to synchronize calls to * its driver. */ struct bus_type *bus; /* type of bus device is on */ //所在bus struct device_driver *driver; /* which driver has allocated this //匹配的driver device */ void *platform_data; /* Platform specific data, device core doesn't touch it */ struct dev_pm_info power; #ifdef CONFIG_NUMA int numa_node; /* NUMA node this device is close to */ #endif u64 *dma_mask; /* dma mask (if dma'able device) */ u64 coherent_dma_mask;/* Like dma_mask, but for alloc_coherent mappings as not all hardware supports 64 bit addresses for consistent allocations such descriptors. */ struct device_dma_parameters *dma_parms; struct list_head dma_pools; /* dma pools (if dma'ble) */ struct dma_coherent_mem *dma_mem; /* internal for coherent mem override */ /* arch specific additions */ struct dev_archdata archdata; #ifdef CONFIG_OF struct device_node *of_node; #endif dev_t devt; /* dev_t, creates the sysfs "dev" */ spinlock_t devres_lock; struct list_head devres_head; struct klist_node knode_class; struct class *class; const struct attribute_group **groups; /* optional groups */ void (*release)(struct device *dev); }; //重点看一下私有属性结构 struct device_private { struct klist klist_children; //子集结构 struct klist_node knode_parent; //父级挂接点 struct klist_node knode_driver; //driver挂接点 struct klist_node knode_bus; //bus挂接点 void *driver_data; struct device *device; //回指 };
接下来详细看一下device的注册device_register:
int device_register(struct device *dev) { device_initialize(dev); //初始化dev return device_add(dev); //添加dev } /****************************** * 先看一下device_initialize(dev) ******************************/ void device_initialize(struct device *dev) { dev->kobj.kset = devices_kset; //可见device和bus都有其起始的kset,而driver没有 kobject_init(&dev->kobj, &device_ktype); //初始化这个kobj并建立层次关系以及属性文件,此时 INIT_LIST_HEAD(&dev->dma_pools); //是放到了总的device文件目录下面 mutex_init(&dev->mutex); lockdep_set_novalidate_class(&dev->mutex); spin_lock_init(&dev->devres_lock); INIT_LIST_HEAD(&dev->devres_head); device_pm_init(dev); set_dev_node(dev, -1); } /****************************** * 再来看一下device_add(dev) ******************************/ int device_add(struct device *dev) { struct device *parent = NULL; struct class_interface *class_intf; int error = -EINVAL; dev = get_device(dev); if (!dev) goto done; if (!dev->p) { error = device_private_init(dev); //初始化dev的私有成员,及其链表操作函数 if (error) goto done; } /* * for statically allocated devices, which should all be converted * some day, we need to initialize the name. We prevent reading back * the name, and force the use of dev_name() */ if (dev->init_name) { dev_set_name(dev, "%s", dev->init_name); //设置名字,给kobj dev->init_name = NULL; } if (!dev_name(dev)) { //名字为空出错退出 error = -EINVAL; goto name_error; } pr_debug("device: '%s': %s/n", dev_name(dev), __func__); parent = get_device(dev->parent); //返回父节点,如果有返回,没有返回NULL setup_parent(dev, parent); /* use parent numa_node */ if (parent) set_dev_node(dev, dev_to_node(parent)); /* first, register with generic layer. */ /* we require the name to be set before, and pass NULL */ error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); //初始化kobj与其父节点的连接 if (error) goto Error; /* notify platform of device entry */ if (platform_notify) platform_notify(dev); error = device_create_file(dev, &uevent_attr); //产生属性文件 if (error) goto attrError; if (MAJOR(dev->devt)) { error = device_create_file(dev, &devt_attr); //在sys下产生dev属性文件 if (error) goto ueventattrError; error = device_create_sys_dev_entry(dev); if (error) goto devtattrError; devtmpfs_create_node(dev); } error = device_add_class_symlinks(dev); if (error) goto SymlinkError; error = device_add_attrs(dev); //增加属性文件 if (error) goto AttrsError; error = bus_add_device(dev); //把device的bus节点挂到bus的设备节点上 if (error) goto BusError; error = dpm_sysfs_add(dev); if (error) goto DPMError; device_pm_add(dev); /* Notify clients of device addition. This call must come * after dpm_sysf_add() and before kobject_uevent(). */ if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev); kobject_uevent(&dev->kobj, KOBJ_ADD); bus_probe_device(dev); //匹配driver if (parent) klist_add_tail(&dev->p->knode_parent, //把该设备的节点挂到其父节点的链表 &parent->p->klist_children); if (dev->class) { mutex_lock(&dev->class->p->class_mutex); /* tie the class to the device */ klist_add_tail(&dev->knode_class, &dev->class->p->class_devices); /* notify any interfaces that the device is here */ list_for_each_entry(class_intf, &dev->class->p->class_interfaces, node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); mutex_unlock(&dev->class->p->class_mutex); } done: put_device(dev); return error; DPMError: bus_remove_device(dev); BusError: device_remove_attrs(dev); AttrsError: device_remove_class_symlinks(dev); SymlinkError: if (MAJOR(dev->devt)) devtmpfs_delete_node(dev); if (MAJOR(dev->devt)) device_remove_sys_dev_entry(dev); devtattrError: if (MAJOR(dev->devt)) device_remove_file(dev, &devt_attr); ueventattrError: device_remove_file(dev, &uevent_attr); attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); Error: cleanup_device_parent(dev); if (parent) put_device(parent); name_error: kfree(dev->p); dev->p = NULL; goto done; } /*********************************************** * 重点看一下bus_probe_device匹配driver以及初始化过程 ***********************************************/ void bus_probe_device(struct device *dev) { struct bus_type *bus = dev->bus; int ret; if (bus && bus->p->drivers_autoprobe) { //设置了自动匹配初始化那么就开始匹配 ret = device_attach(dev); WARN_ON(ret < 0); } } /****************** * 继续device_attach ******************/ int device_attach(struct device *dev) { int ret = 0; device_lock(dev); if (dev->driver) { //默认指定了driver就直接绑定 ret = device_bind_driver(dev); if (ret == 0) ret = 1; else { dev->driver = NULL; ret = 0; } } else { //没有指定就进行遍历匹配 pm_runtime_get_noresume(dev); ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); pm_runtime_put_sync(dev); } device_unlock(dev); return ret; } /************************** * 再来看device_bind_driver分支 **************************/ int device_bind_driver(struct device *dev) { int ret; ret = driver_sysfs_add(dev); if (!ret) driver_bound(dev); //主要是完成了将私有成员的driver节点挂到 return ret; //了driver的设备链表 } /************************** * 先看bus_for_each_drv分支 **************************/ int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, void *data, int (*fn)(struct device_driver *, void *)) { struct klist_iter i; struct device_driver *drv; int error = 0; if (!bus) return -EINVAL; klist_iter_init_node(&bus->p->klist_drivers, &i, //和driver遍历device类似,从头开始遍历bus的driver链表 start ? &start->p->knode_bus : NULL); //发现一个driver就调用fn即__device_attach进行匹配 while ((drv = next_driver(&i)) && !error) error = fn(drv, data); klist_iter_exit(&i); return error; } /********************************* * 最后来看一下__device_attach这个函数 *********************************/ static int __device_attach(struct device_driver *drv, void *data) { struct device *dev = data; if (!driver_match_device(drv, dev)) return 0; return driver_probe_device(drv, dev); } /* 对比driver的注册最后调用的__driver_attach可以发现其实质是一样的,都最后归宿到了 这driver_match_device,driver_probe_device两个函数,本质参数的和谐做到了通用 性在这里就不继续分析了,不是很清楚的可以看前一篇文章driver最后一部分的分析 ^_^ */
以上便是device的注册,可以发现device和driver围绕着bus最后有种殊途同归的感觉,下面结合driver的流程给出一个框图
以便更明确其间的流程:
相关文章推荐
- linux设备模型之bus,device,driver分析一
- linux设备模型之bus,device,driver分析一
- linux设备模型之bus,device,driver分析二
- linux驱动编写之十三(设备模型之sysfs,bus,device,driver源代码分析)
- linux设备模型之bus,device,driver分析一
- linux设备模型之bus,device,driver分析二
- linux设备模型之bus,device,driver分析一
- linux设备模型bus,device,driver
- LINUX设备驱动之设备模型五--device&driver&bus(三)
- Linux设备模型分析之device_driver(基于3.10.1内核)
- linux设备模型bus,device,driver
- LINUX设备驱动之设备模型三--device&driver&bus
- Linux内核部件分析 设备驱动模型之device-driver
- linux设备模型bus,device,driver
- LINUX设备模型BUS,DEVICE,DRIVER
- linux 设备模型中 bus 、device 、driver 三者关系
- Linux设备模型中三个很重要的概念: 总线,设备,驱动.即bus,device,driver
- Linux内核部件分析--设备驱动模型之device-driver
- Linux设备模型分析之device_driver(基于3.10.1内核)
- linux设备模型bus,device,driver