为什么两个name的名字必须匹配才能实现device和driver的绑定?
(1)在内核初始化时kernel_init()->do_basic_setup()->driver_init()->platform_bus_init()初始化platform_bus(虚拟总线);
(2)设备注册的时候platform_device_register()->platform_device_add()->(pdev->dev.bus = &platform_bus_type)把设备挂在虚拟的platform bus下;
(3)驱动注册的时候platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev(),对每个挂在虚拟的platform bus的设备作__driver_attach()->driver_probe_device(),判断drv->bus->match()是否存在并且是否执行成功,此时通过指针执行platform_match,比较strncmp(pdev->name, drv->name, BUS_ID_SIZE),如果相符就调用really_probe(实际就是执行的相应设备的platform_driver->probe(platform_device),注意platform_drv_probe的_dev参数是由bus_for_each_dev的next_device获得)开始真正的探测加载,如果probe成功则绑定该设备到该驱动。
#include <linux/platform_device.h> #include <linux/init.h> #include <linux/module.h> static int __init test_probe(struct platform_device *pdev) { int err = 0; return err; } static int test_remove(struct platform_device *pdev) { return 0; } static struct platform_device test_device = { .name = "test_ts", .id = -1, }; static struct platform_driver test_driver = { .probe = test_probe, .remove = test_remove, .driver = { .name = "test_ts", .owner = THIS_MODULE, }, }; static int __devinit test_init(void) { platform_device_register(&test_device); return platform_driver_register(&test_driver); } static void __exit test_exit(void) { platform_device_unregister(&test_device); platform_driver_unregister(&test_driver); } module_init(test_init); module_exit(test_exit); MODULE_AUTHOR("zwolf"); MODULE_DESCRIPTION("Module test"); MODULE_LICENSE("GPL"); MODULE_ALIAS("test");
#Makefile obj-m:=test.o KDIR:=/lib/modules/2.6.27-7-generic/build PWD:=$(shell pwd) default: $(MAKE) -C $(KDIR) M=$(PWD) modules
int __init buses_init(void) { bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); if (!bus_kset) return -ENOMEM; return 0; }
struct kset *kset_create_and_add(const char *name, struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) //传递进来的参数为("bus", &bus_uevent_ops, NULL) { struct kset *kset; int error; //创建一个kset容器 kset = kset_create(name, uevent_ops, parent_kobj); if (!kset) return NULL; //注册创建的kset容器 error = kset_register(kset); if (error) { kfree(kset); return NULL; } return kset; }
static struct kset *kset_create(const char *name, struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) //传递进来的参数为("bus", &bus_uevent_ops, NULL) { struct kset *kset; //为kset分配内存 kset = kzalloc(sizeof(*kset), GFP_KERNEL); if (!kset) return NULL; //设置kset中kobject的名字,这里为bus kobject_set_name(&kset->kobj, name); //设置uevent操作集,这里为bus_uevent_ops kset->uevent_ops = uevent_ops; //设置父对象,这里为NULL kset->kobj.parent = parent_kobj; //设置容器操作集 kset->kobj.ktype = &kset_ktype; //设置父容器 kset->kobj.kset = NULL; return kset; }
int kset_register(struct kset *k) { int err; if (!k) return -EINVAL; //初始化 kset_init(k); //添加该容器 err = kobject_add_internal(&k->kobj); if (err) return err; kobject_uevent(&k->kobj, KOBJ_ADD); return 0; }
//kset_init进行一些固定的初始化操作,里面没有我们需要关心的内容 //kobject_add_internal为重要的一个函数,他对kset里kobj的从属关系进行解析,搭建正确的架构 static int kobject_add_internal(struct kobject *kobj) { int error = 0; struct kobject *parent; //检测kobj是否为空 if (!kobj) return -ENOENT; //检测kobj名字是否为空 if (!kobj->name || !kobj->name[0]) { pr_debug("kobject: (%p): attempted to be registered with empty " "name!/n", kobj); WARN_ON(1); return -EINVAL; } //提取父对象 parent = kobject_get(kobj->parent); /* join kset if set, use it as parent if we do not already have one */ //父容器存在则设置父对象 if (kobj->kset) {//在bus的kset中为空,所以不会进入到下面的代码 //检测是否已经设置父对象 if (!parent) //无则使用父容器为父对象 parent = kobject_get(&kobj->kset->kobj); //添加该kobj到父容器的链表中 kobj_kset_join(kobj); //设置父对象 kobj->parent = parent; } pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'/n", kobject_name(kobj), kobj, __func__, parent ? kobject_name(parent) : "<NULL>", kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>"); //建立相应的目录 error = create_dir(kobj); if (error) { kobj_kset_leave(kobj); kobject_put(parent); kobj->parent = NULL; if (error == -EEXIST) printk(KERN_ERR "%s failed for %s with " "-EEXIST, don't try to register things with " "the same name in the same directory./n", __func__, kobject_name(kobj)); else printk(KERN_ERR "%s failed for %s (%d)/n", __func__, kobject_name(kobj), error); dump_stack(); } else kobj->state_in_sysfs = 1; return error; }
<span style="font-family:Arial;BACKGROUND-COLOR: #ffffff"></span> int __init devices_init(void) { devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); if (!devices_kset) return -ENOMEM; return 0; }
int __init platform_bus_init(void) { int error; //注册到devices目录中 error = device_register(&platform_bus); if (error) return error; //注册到bus目录中 error = bus_register(&platform_bus_type); if (error) device_unregister(&platform_bus); return error; }
int device_register(struct device *dev) { //初始化dev结构 device_initialize(dev); //添加dev至目录 return device_add(dev); } void device_initialize(struct device *dev) { //重要的一步,指明了父容器为devices_kset,而devices_kset的注册在前面已经介绍过了 dev->kobj.kset = devices_kset; //初始化kobj的ktype为device_ktype kobject_init(&dev->kobj, &device_ktype); klist_init(&dev->klist_children, klist_children_get, klist_children_put); INIT_LIST_HEAD(&dev->dma_pools); INIT_LIST_HEAD(&dev->node); init_MUTEX(&dev->sem); spin_lock_init(&dev->devres_lock); INIT_LIST_HEAD(&dev->devres_head); device_init_wakeup(dev, 0); set_dev_node(dev, -1); } int device_add(struct device *dev) { struct device *parent = NULL; struct class_interface *class_intf; int error; dev = get_device(dev); if (!dev || !strlen(dev->bus_id)) { error = -EINVAL; goto Done; } pr_debug("device: '%s': %s/n", dev->bus_id, __func__); parent = get_device(dev->parent); setup_parent(dev, parent); if (parent) set_dev_node(dev, dev_to_node(parent)); //设置dev->kobj的名字和父对象,并建立相应的目录 error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id); if (error) goto Error; if (platform_notify) platform_notify(dev); if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev); //建立uevent文件 error = device_create_file(dev, &uevent_attr); if (error) goto attrError; if (MAJOR(dev->devt)) { error = device_create_file(dev, &devt_attr); if (error) goto ueventattrError; } //建立subsystem连接文件连接到所属class,这里没有设置class对象所以不会建立 error = device_add_class_symlinks(dev); if (error) goto SymlinkError; //建立dev的描述文件,这里没有设置描述文件所以不会建立 error = device_add_attrs(dev); if (error) goto AttrsError; //建立链接文件至所属bus,这里没有设置所属bus所以不会建立 error = bus_add_device(dev); if (error) goto BusError; //添加power文件,因为platform不属于设备,所以不会建立power文件 error = device_pm_add(dev); if (error) goto PMError; kobject_uevent(&dev->kobj, KOBJ_ADD); //检测驱动中有无适合的设备进行匹配,但没有设置bus,所以不会进行匹配 bus_attach_device(dev); if (parent) klist_add_tail(&dev->knode_parent, &parent->klist_children); if (dev->class) { down(&dev->class->sem); list_add_tail(&dev->node, &dev->class->devices); list_for_each_entry(class_intf, &dev->class->interfaces, node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); up(&dev->class->sem); } Done: put_device(dev); return error; PMError: bus_remove_device(dev); BusError: if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_DEL_DEVICE, dev); device_remove_attrs(dev); AttrsError: device_remove_class_symlinks(dev); SymlinkError: 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); goto Done; } 在kobject_add-> kobject_add_varg-> kobject_add_internal中 //提取父对象,因为没有设置,所以为空 parent = kobject_get(kobj->parent); //父容器存在则设置父对象,在前面的dev->kobj.kset = devices_kset中设为了devices_kset if (kobj->kset) { //检测是否已经设置父对象 if (!parent) //无则使用父容器为父对象 parent = kobject_get(&kobj->kset->kobj); //添加该kobj到父容器的链表中 kobj_kset_join(kobj); //设置父对象 kobj->parent = parent; }
struct bus_type platform_bus_type = { .name = "platform", .dev_attrs = platform_dev_attrs, .match = platform_match, .uevent = platform_uevent, .suspend = platform_suspend, .suspend_late = platform_suspend_late, .resume_early = platform_resume_early, .resume = platform_resume, }; int bus_register(struct bus_type *bus) { int retval; //声明一个总线私有数据并分配空间 struct bus_type_private *priv; priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL); if (!priv) return -ENOMEM; //互相关联 priv->bus = bus; bus->p = priv; BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier); //设置私有数据中kobj对象的名字 retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name); if (retval) goto out; //设置父容器为bus_kset,操作集为bus_ktype priv->subsys.kobj.kset = bus_kset; priv->subsys.kobj.ktype = &bus_ktype; priv->drivers_autoprobe = 1; //注册bus容器 retval = kset_register(&priv->subsys); if (retval) goto out; //建立uevent属性文件 retval = bus_create_file(bus, &bus_attr_uevent); if (retval) goto bus_uevent_fail; //建立devices目录 priv->devices_kset = kset_create_and_add("devices", NULL, &priv->subsys.kobj); if (!priv->devices_kset) { retval = -ENOMEM; goto bus_devices_fail; } //建立drivers目录 priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj); if (!priv->drivers_kset) { retval = -ENOMEM; goto bus_drivers_fail; } //初始化klist_devices和klist_drivers链表 klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); klist_init(&priv->klist_drivers, NULL, NULL); //增加probe属性文件 retval = add_probe_files(bus); if (retval) goto bus_probe_files_fail; //增加总线的属性文件 retval = bus_add_attrs(bus); if (retval) goto bus_attrs_fail; pr_debug("bus: '%s': registered/n", bus->name); return 0; bus_attrs_fail: remove_probe_files(bus); bus_probe_files_fail: kset_unregister(bus->p->drivers_kset); bus_drivers_fail: kset_unregister(bus->p->devices_kset); bus_devices_fail: bus_remove_file(bus, &bus_attr_uevent); bus_uevent_fail: kset_unregister(&bus->p->subsys); kfree(bus->p); out: return retval; } 在kset_register-> kobject_add_internal中 //提取父对象,因为没有设置父对象,所以为空 parent = kobject_get(kobj->parent); //父容器存在则设置父对象,在上文中设置了父容器priv->subsys.kobj.kset = bus_kset if (kobj->kset) { //检测是否已经设置父对象 if (!parent) //无则使用父容器为父对象 parent = kobject_get(&kobj->kset->kobj); //添加该kobj到父容器的链表中 kobj_kset_join(kobj); //设置父对象 kobj->parent = parent; }
//现在来看kset_create_and_add("devices", NULL,&priv->subsys.kobj); struct kset *kset_create_and_add(const char *name, struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) //参数为"devices", NULL,&priv->subsys.kobj { struct kset *kset; int error; //创建一个kset容器 kset = kset_create(name, uevent_ops, parent_kobj); if (!kset) return NULL; //注册创建的kset容器 error = kset_register(kset); if (error) { kfree(kset); return NULL; } return kset; } 在kset_create 中比较重要的操作为 kset->kobj.ktype = &kset_ktype //设置了ktype,为kset_ktype kset->kobj.parent = parent_kobj; //设置了父对象,为priv->subsys.kobj,也就是platform_bus_type->p->subsys.kobj kset->kobj.kset = NULL; //设置父容器为空 在kset_register中 //提取父对象 parent = kobject_get(kobj->parent); //在之前设置为了 //父容器存在则设置父对象,由于父容器为空,不执行以下代码 if (kobj->kset) { //检测是否已经设置父对象 if (!parent) //无则使用父容器为父对象 parent = kobject_get(&kobj->kset->kobj); //添加该kobj到父容器的链表中 kobj_kset_join(kobj); //设置父对象 kobj->parent = parent; }
int platform_device_register(struct platform_device *pdev) { //设备属性的初始化 device_initialize(&pdev->dev); //将设备添加进platform里 return platform_device_add(pdev); } void device_initialize(struct device *dev) { dev->kobj.kset = devices_kset; //设置kset为devices_kset,则将设备挂接上了devices目录 kobject_init(&dev->kobj, &device_ktype); //初始化kobeject,置ktype为device_ktype klist_init(&dev->klist_children, klist_children_get, klist_children_put); INIT_LIST_HEAD(&dev->dma_pools); INIT_LIST_HEAD(&dev->node); init_MUTEX(&dev->sem); spin_lock_init(&dev->devres_lock); INIT_LIST_HEAD(&dev->devres_head); device_init_wakeup(dev, 0); set_dev_node(dev, -1); } int platform_device_add(struct platform_device *pdev) { int i, ret = 0; if (!pdev) return -EINVAL; //检测是否设置了dev中的parent,无则赋为platform_bus if (!pdev->dev.parent) pdev->dev.parent = &platform_bus; //设置dev中的bus为platform_bus_type pdev->dev.bus = &platform_bus_type; //检测id,id为-1表明该设备只有一个,用设备名为bus_id //不为1则表明该设备有数个,需要用序号标明bus_id if (pdev->id != -1) snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name, pdev->id); else strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE); //增加资源到资源树中 for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource; if (r->name == NULL) r->name = pdev->dev.bus_id; p = r->parent; if (!p) { if (r->flags & IORESOURCE_MEM) p = &iomem_resource; else if (r->flags & IORESOURCE_IO) p = &ioport_resource; } if (p && insert_resource(p, r)) { printk(KERN_ERR "%s: failed to claim resource %d/n",pdev->dev.bus_id, i); ret = -EBUSY; goto failed; } } pr_debug("Registering platform device '%s'. Parent at %s/n",pdev->dev.bus_id, pdev->dev.parent->bus_id); //添加设备到设备层次中 ret = device_add(&pdev->dev); if (ret == 0) return ret; failed: while (--i >= 0) if (pdev->resource.flags & (IORESOURCE_MEM|IORESOURCE_IO)) release_resource(&pdev->resource); return ret; } int device_add(struct device *dev) { struct device *parent = NULL; struct class_interface *class_intf; int error; dev = get_device(dev); if (!dev || !strlen(dev->bus_id)) { error = -EINVAL; goto Done; } pr_debug("device: '%s': %s/n", dev->bus_id, __func__); //取得上层device,而dev->parent的赋值是在platform_device_add中的pdev->dev.parent = &platform_bus完成的 parent = get_device(dev->parent); //以上层devices为准重设dev->kobj.parent setup_parent(dev, parent); if (parent) set_dev_node(dev, dev_to_node(parent)); //设置dev->kobj的名字和父对象,并建立相应目录 error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id); if (error) goto Error; if (platform_notify) platform_notify(dev); //一种新型的通知机制,但是platform中没有设置相应的结构,所以在这里跳过 /* notify clients of device entry (new way) */ if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier,BUS_NOTIFY_ADD_DEVICE, dev); //建立uevent文件 error = device_create_file(dev, &uevent_attr); if (error) goto attrError; //设备有设备号则建立dev文件 if (MAJOR(dev->devt)) { error = device_create_file(dev, &devt_attr); if (error) goto ueventattrError; } //建立subsystem连接文件连接到所属class error = device_add_class_symlinks(dev); if (error) goto SymlinkError; //添加dev的描述文件 error = device_add_attrs(dev); if (error) goto AttrsError; //添加链接文件至所属bus error = bus_add_device(dev); if (error) goto BusError; //添加power文件 error = device_pm_add(dev); if (error) goto PMError; kobject_uevent(&dev->kobj, KOBJ_ADD); //检测驱动中有无适合的设备进行匹配,现在只添加了设备,还没有加载驱动,所以不会进行匹配 bus_attach_device(dev); if (parent) klist_add_tail(&dev->knode_parent, &parent->klist_children); if (dev->class) { down(&dev->class->sem); list_add_tail(&dev->node, &dev->class->devices); list_for_each_entry(class_intf, &dev->class->interfaces, node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); up(&dev->class->sem); } Done: put_device(dev); return error; PMError: bus_remove_device(dev); BusError: if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier,BUS_NOTIFY_DEL_DEVICE, dev); device_remove_attrs(dev); AttrsError: device_remove_class_symlinks(dev); SymlinkError: 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); goto Done; } static void setup_parent(struct device *dev, struct device *parent) { struct kobject *kobj; //取得上层device的kobj kobj = get_device_parent(dev, parent); //kobj不为空则重设dev->kobj.parent if (kobj) dev->kobj.parent = kobj; } static struct kobject *get_device_parent(struct device *dev, struct device *parent) { int retval; //因为dev->class为空,所以跳过这段代码 if (dev->class) { struct kobject *kobj = NULL; struct kobject *parent_kobj; struct kobject *k; if (parent == NULL) parent_kobj = virtual_device_parent(dev); else if (parent->class) return &parent->kobj; else parent_kobj = &parent->kobj; spin_lock(&dev->class->class_dirs.list_lock); list_for_each_entry(k, &dev->class->class_dirs.list, entry) if (k->parent == parent_kobj) { kobj = kobject_get(k); break; } spin_unlock(&dev->class->class_dirs.list_lock); if (kobj) return kobj; k = kobject_create(); if (!k) return NULL; k->kset = &dev->class->class_dirs; retval = kobject_add(k, parent_kobj, "%s", dev->class->name); if (retval < 0) { kobject_put(k); return NULL; } return k; } if (parent) //返回上层device的kobj return &parent->kobj; return NULL; } 在bus_attach_device中虽然没有成功进行匹配,但是有很重要的一步为之后正确的匹配打下基础 void bus_attach_device(struct device *dev) { struct bus_type *bus = dev->bus; int ret = 0; if (bus) { if (bus->p->drivers_autoprobe) ret = device_attach(dev); WARN_ON(ret < 0); if (ret >= 0) klist_add_tail(&dev->knode_bus, &bus->p->klist_devices); } }
然后platform_driver_unregister,他的参数 test_driver的结构如下 static struct platform_driver test_driver = { .probe = test_probe, .remove = test_remove, .driver = { .name = "test_ts", .owner = THIS_MODULE, }, }; int platform_driver_register(struct platform_driver *drv) { drv->driver.bus = &platform_bus_type; if (drv->probe) drv->driver.probe = platform_drv_probe; if (drv->remove) drv->driver.remove = platform_drv_remove; if (drv->shutdown) drv->driver.shutdown = platform_drv_shutdown; if (drv->suspend) drv->driver.suspend = platform_drv_suspend; if (drv->resume) drv->driver.resume = platform_drv_resume; return driver_register(&drv->driver); }
int driver_register(struct device_driver *drv) { int ret; struct device_driver *other; //检测总线的操作函数和驱动的操作函数是否同时存在,同时存在则提示使用总线提供的操作函数 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); printk(KERN_ERR "Error: Driver '%s' is already registered, “"aborting.../n", drv->name); return -EEXIST; } //添加驱动到总线上 ret = bus_add_driver(drv); if (ret) return ret; ret = driver_add_groups(drv, drv->groups); if (ret) bus_remove_driver(drv); return ret; } int bus_add_driver(struct device_driver *drv) { struct bus_type *bus; struct driver_private *priv; int error = 0; //取bus结构 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); if (!priv) { error = -ENOMEM; goto out_put_bus; } //初始化klist_devices链表 klist_init(&priv->klist_devices, NULL, NULL); //互相关联 priv->driver = drv; drv->p = priv; //设置私有数据的父容器,在这一步中,设置了kset为platform下的drivers_kset结构,也就是drivers呢个目录 priv->kobj.kset = bus->p->drivers_kset; //初始化kobj对象,设置容器操作集并建立相应的目录,这里由于没有提供parent,所以会使用父容器中的kobj为父对象 error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, "%s", drv->name); if (error) goto out_unregister; //检测所属总线的drivers_autoprobe属性是否为真 //为真则进行与设备的匹配,到这里,就会与我们之前注册的test_device连接上了,至于如何连接,进行了什么操作,将在别的文章中详细描述 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); //建立uevent属性文件 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) { printk(KERN_ERR "%s: driver_add_attrs(%s) failed/n",__func__, drv->name); } error = add_bind_files(drv); if (error) { printk(KERN_ERR "%s: add_bind_files(%s) failed/n",__func__, drv->name); } kobject_uevent(&priv->kobj, KOBJ_ADD); return error; out_unregister: kobject_put(&priv->kobj); out_put_bus: bus_put(bus); return error; }
void bus_attach_device(struct device *dev) { struct bus_type *bus = dev->bus; int ret = 0; if (bus) { if (bus->p->drivers_autoprobe) ret = device_attach(dev); WARN_ON(ret < 0); if (ret >= 0) klist_add_tail(&dev->knode_bus, &bus->p->klist_devices); } }
retval = bus_create_file(bus, &bus_attr_drivers_autoprobe); bus_attr_drivers_autoprobe这个结构由一系列的宏进行组装 static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO, show_drivers_autoprobe, store_drivers_autoprobe); #define BUS_ATTR(_name, _mode, _show, _store) / struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store) #define __ATTR(_name,_mode,_show,_store) { / .attr = {.name = __stringify(_name), .mode = _mode }, / .show = _show, / .store = _store, / }
struct bus_attribute bus_attr_drivers_autoprobe { .attr = { .name = “drivers_autoprobe”, .mode = S_IWUSR | S_IRUGO }, .show = show_drivers_autoprobe, .store = store_drivers_autoprobe, }
int bus_create_file(struct bus_type *bus, struct bus_attribute *attr) //参数为(bus, &bus_attr_drivers_autoprobe) { int error; if (bus_get(bus)) { error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr); bus_put(bus); } else error = -EINVAL; return error; } int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) //参数为(&bus->p->subsys.kobj, &attr->attr) { BUG_ON(!kobj || !kobj->sd || !attr); return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR); } int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,int type) //参数为(&bus->p->subsys.kobj ->sd, &attr->attr, SYSFS_KOBJ_ATTR) { return sysfs_add_file_mode(dir_sd, attr, type, attr->mode); } int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, const struct attribute *attr, int type, mode_t amode) //整理一下参数,现在应该为 //(&platform_bus_type->p->subsys.kobj ->sd, &bus_attr_drivers_autoprobe->attr, SYSFS_KOBJ_ATTR, &bus_attr_drivers_autoprobe->attr->mode) { umode_t mode = (amode & S_IALLUGO) | S_IFREG; struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; int rc; //在这一步中可以看出新建了一个节点 sd = sysfs_new_dirent(attr->name, mode, type); if (!sd) return -ENOMEM; //这一步挂载了&bus_attr_drivers_autoprobe->attr到节点中,为以后提取attr及上层结构做准备 sd->s_attr.attr = (void *)attr; // dir_sd也就是上层目录,在这里为platform_bus_type->p->subsys.kobj ->sd //也就是/sys/bus/platform这个目录 sysfs_addrm_start(&acxt, dir_sd); rc = sysfs_add_one(&acxt, sd); sysfs_addrm_finish(&acxt); if (rc) sysfs_put(sd); return rc; } struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) { char *dup_name = NULL; struct sysfs_dirent *sd; if (type & SYSFS_COPY_NAME) { name = dup_name = kstrdup(name, GFP_KERNEL); if (!name) return NULL; } sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); if (!sd) goto err_out1; if (sysfs_alloc_ino(&sd->s_ino)) goto err_out2; atomic_set(&sd->s_count, 1); atomic_set(&sd->s_active, 0); sd->s_name = name; //节点的名字为&bus_attr_drivers_autoprobe->attr->name 也就是drivers_autoprobe sd->s_mode = mode; sd->s_flags = type; //节点的type为SYSFS_KOBJ_ATTR return sd; err_out2: kmem_cache_free(sysfs_dir_cachep, sd); err_out1: kfree(dup_name); return NULL; }
static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { struct dentry *ret = NULL; struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; struct sysfs_dirent *sd; struct inode *inode; mutex_lock(&sysfs_mutex); sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); if (!sd) { ret = ERR_PTR(-ENOENT); goto out_unlock; } //节点的初始化在这里 inode = sysfs_get_inode(sd); if (!inode) { ret = ERR_PTR(-ENOMEM); goto out_unlock; } dentry->d_op = &sysfs_dentry_ops; dentry->d_fsdata = sysfs_get(sd); d_instantiate(dentry, inode); d_rehash(dentry); out_unlock: mutex_unlock(&sysfs_mutex); return ret; } struct inode * sysfs_get_inode(struct sysfs_dirent *sd) { struct inode *inode; inode = iget_locked(sysfs_sb, sd->s_ino); if (inode && (inode->i_state & I_NEW)) //为节点赋值 sysfs_init_inode(sd, inode); return inode; } static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) { struct bin_attribute *bin_attr; inode->i_blocks = 0; inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; inode->i_op = &sysfs_inode_operations; inode->i_ino = sd->s_ino; lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key); if (sd->s_iattr) { set_inode_attr(inode, sd->s_iattr); } else set_default_inode_attr(inode, sd->s_mode); //判断类型 switch (sysfs_type(sd)) { case SYSFS_DIR: inode->i_op = &sysfs_dir_inode_operations; inode->i_fop = &sysfs_dir_operations; inode->i_nlink = sysfs_count_nlink(sd); break; //还记得在注册的时候有一个参数为SYSFS_KOBJ_ATTR赋到了sd->s_flags上面吧 case SYSFS_KOBJ_ATTR: inode->i_size = PAGE_SIZE; inode->i_fop = &sysfs_file_operations; break; case SYSFS_KOBJ_BIN_ATTR: bin_attr = sd->s_bin_attr.bin_attr; inode->i_size = bin_attr->size; inode->i_fop = &bin_fops; break; case SYSFS_KOBJ_LINK: inode->i_op = &sysfs_symlink_inode_operations; break; default: BUG(); } unlock_new_inode(inode); } sysfs_file_operations的结构如下,之后open和read,write都明了了 const struct file_operations sysfs_file_operations = { .read = sysfs_read_file, .write = sysfs_write_file, .llseek = generic_file_llseek, .open = sysfs_open_file, .release = sysfs_release, .poll = sysfs_poll, };
static int sysfs_open_file(struct inode *inode, struct file *file) { struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; //要重的取值,在这里取得了drivers_autoprobe的目录platform的kproject struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; struct sysfs_buffer *buffer; struct sysfs_ops *ops; int error = -EACCES; if (!sysfs_get_active_two(attr_sd)) return -ENODEV; if (kobj->ktype && kobj->ktype->sysfs_ops) //这里可谓是ktype实现中的核心,在这里ops设置成了platform_bus_type中kobject->ktype的sysfs_ops ops = kobj->ktype->sysfs_ops; else { printk(KERN_ERR "missing sysfs attribute operations for ""kobject: %s/n", kobject_name(kobj)); WARN_ON(1); goto err_out; } if (file->f_mode & FMODE_WRITE) { if (!(inode->i_mode & S_IWUGO) || !ops->store) goto err_out; } if (file->f_mode & FMODE_READ) { if (!(inode->i_mode & S_IRUGO) || !ops->show) goto err_out; } error = -ENOMEM; buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); if (!buffer) goto err_out; mutex_init(&buffer->mutex); buffer->needs_read_fill = 1; //然后将设置好的ops挂载到buffer上 buffer->ops = ops; //再将buffer挂载到file->private_data中 file->private_data = buffer; error = sysfs_get_open_dirent(attr_sd, buffer); if (error) goto err_free; sysfs_put_active_two(attr_sd); return 0; err_free: kfree(buffer); err_out: sysfs_put_active_two(attr_sd); return error; }
sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct sysfs_buffer * buffer = file->private_data; ssize_t retval = 0; mutex_lock(&buffer->mutex); if (buffer->needs_read_fill || *ppos == 0) { //主要操作在fill_read_buffer中 retval = fill_read_buffer(file->f_path.dentry,buffer); if (retval) goto out; } pr_debug("%s: count = %zd, ppos = %lld, buf = %s/n",__func__, count, *ppos, buffer->page); retval = simple_read_from_buffer(buf, count, ppos, buffer->page, buffer->count); out: mutex_unlock(&buffer->mutex); return retval; } static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) { struct sysfs_dirent *attr_sd = dentry->d_fsdata; //取得父目录的kobject,也就是platform的kobject struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; //还记得这个buffer->ops在什么时候进行赋值的么? struct sysfs_ops * ops = buffer->ops; int ret = 0; ssize_t count; if (!buffer->page) buffer->page = (char *) get_zeroed_page(GFP_KERNEL); if (!buffer->page) return -ENOMEM; if (!sysfs_get_active_two(attr_sd)) return -ENODEV; buffer->event = atomic_read(&attr_sd->s_attr.open->event); //调用ops->show 也就是bus_sysfs_ops->show 具体就是bus_attr_show了 //参数为父目录的kobject, bus_attr_drivers_autoprobe->attr,和一段char信息 count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page); sysfs_put_active_two(attr_sd); if (count >= (ssize_t)PAGE_SIZE) { print_symbol("fill_read_buffer: %s returned bad count/n", (unsigned long)ops->show); /* Try to struggle along */ count = PAGE_SIZE - 1; } if (count >= 0) { buffer->needs_read_fill = 0; buffer->count = count; } else { ret = count; } return ret; }
static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,char *buf) { //提取attr的上层结构,也就是bus_attr_drivers_autoprobe struct bus_attribute *bus_attr = to_bus_attr(attr); //提取kobj的上上层结构,也就是bus_type_private struct bus_type_private *bus_priv = to_bus(kobj); ssize_t ret = 0; if (bus_attr->show) //终于到了这里,最后的调用,调用bus_attr_drivers_autoprobe.show ,也就是show_drivers_autoprobe //参数为bus_priv->bus,也就是platform_bus_type , 及一段char信息 ret = bus_attr->show(bus_priv->bus, buf); return ret; } static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf) { return sprintf(buf, "%d/n", bus->p->drivers_autoprobe); }
static ssize_t store_drivers_autoprobe(struct bus_type *bus, const char *buf, size_t count) { if (buf[0] == '0') bus->p->drivers_autoprobe = 0; else bus->p->drivers_autoprobe = 1; return count; }
struct kobject { const char *name; //kobject的名字 struct kref kref; //kobject的原子操作 struct list_head entry; struct kobject *parent; //父对象 struct kset *kset; //父容器 struct kobj_type *ktype; //ktype struct sysfs_dirent *sd; //文件节点 unsigned int state_initialized:1; unsigned int state_in_sysfs:1; unsigned int state_add_uevent_sent:1; unsigned int state_remove_uevent_sent:1; };