kobject,kset,子系统层次结构 、platform_device platform_driver

来源:互联网 发布:局部全局优化算法 编辑:程序博客网 时间:2024/06/08 00:10

为什么两个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成功则绑定该设备到该驱动。

 

个人对kobject的一点研究

kobject,kset,子系统层次结构

在LINUX中最让人不解的大概就是/sys下面的内容了

下面首先让我们来创建一个简单的platform设备,并从这个设备的视角进行深入,在此篇文章的深入过程中,我们只看kobeject的模型
我所使用的内核版本号为2.6.26,操作系统的内核版本号为2.6.27-7,暂未发现2.6.27-7与2.6.26的重大不同

首先写一个简单的模块
[cpp] view plain copy
  1. #include <linux/platform_device.h>  
  2. #include <linux/init.h>  
  3. #include <linux/module.h>  
  4.   
  5. static int __init test_probe(struct platform_device *pdev)  
  6. {  
  7.         int err = 0;  
  8.         return err;  
  9. }  
  10.   
  11. static int test_remove(struct platform_device *pdev)  
  12. {  
  13.         return 0;  
  14. }  
  15. static struct platform_device test_device = {  
  16.         .name = "test_ts",  
  17.         .id = -1,  
  18. };  
  19.   
  20. static struct platform_driver test_driver = {  
  21.         .probe                = test_probe,  
  22.         .remove                = test_remove,  
  23.         .driver                = {  
  24.                 .name        = "test_ts",  
  25.                 .owner        = THIS_MODULE,  
  26.         },  
  27. };  
  28.   
  29. static int __devinit test_init(void)  
  30. {  
  31.         platform_device_register(&test_device);          
  32.         return platform_driver_register(&test_driver);  
  33. }  
  34.   
  35. static void __exit test_exit(void)  
  36. {  
  37.         platform_device_unregister(&test_device);  
  38.         platform_driver_unregister(&test_driver);  
  39. }  
  40.   
  41. module_init(test_init);  
  42. module_exit(test_exit);  
  43.   
  44. MODULE_AUTHOR("zwolf");  
  45. MODULE_DESCRIPTION("Module test");  
  46. MODULE_LICENSE("GPL");  
  47. MODULE_ALIAS("test");  

接下来是makefile

[cpp] view plain copy
  1. #Makefile  
  2.   
  3. obj-m:=test.o  
  4. KDIR:=/lib/modules/2.6.27-7-generic/build  
  5. PWD:=$(shell pwd)  
  6.   
  7. default:  
  8.         $(MAKE) -C $(KDIR) M=$(PWD) modules  

KDIR中的目录请改为各位实际运行中的内核目录

make之后进行模块的加载 sudo insmod ./test.ko

现在到sys目录中查看我们的设备是否已经加载上了

首先是/sys/bus/platform/devices/

在devices下,每一个连接文件都代表了一个设备

ls可看见test_ts,进入test_ts,ls可发现driver这个链接文件,ls-l查看,发现这个文件是连到/sys/bus/platform/drivers/test_ts的

这里需要说明的是连接的含义,并不是driver驱动存在于test_ts这个设备中,而是test_ts使用的驱动为/sys/bus/platform/drivers/test_ts

现在换到/sys/bus/platform/drivers这个目录下

ls查看会发现这里的文件都为目录,而非连接文件,说明这是驱动真正放置的位置

现在进入test_ts目录,然后ls,发现有一个test_ts的连接文件,ls –l查看可发现该文件连接到/sys/devices/platform/test_ts下

回到/sys/bus/platform/devices/下ls –l也会发现test_ts连接到/sys/devices/platform/test_ts

为什么test_ts这个设备放置于/sys/devices/platform下,而不是/sys/bus/platform/devices下呢

我认为和直观性有关,在sys下有这么几个目录block  bus  class  dev  devices  firmware  kernel  module  fs power
devices很直观的说明了设备在这个目录下,便于大家查找
而/sys/bus/platform/devices下的连接是为了分类查找

画了张目录图,如下,绿色框的为连接文件,绿色线条为连接的对象

 

题外话:我自身对于这样的分类不是很喜欢,臃肿 重复  而且信息也不好规划,希望在以后的版本能对sys进行大的改造


现在来看另两个图,也就是构成sys的核心kobject,首先第一个是我去掉了连接部分的内容  也就是绿色线条的目录图
第二个是组成这个目录图的核心,kobject图,我也叫他层次图
 
 
不看大号绿色箭头右边的内容的话是不是发现两个架构相同?
对的,kobject的层次决定了目录的结构
kobeject图很大,但也不要担心,里面的内容其实不多,基础框架涉及3个主要结构kset kobject和ktype
在说明test_ts的注册之前,先让我们看一下sys下的两个基础目录bus,devices

首先是bus
bus的注册在/drivers/base/bus.c里
[cpp] view plain copy
  1. int __init buses_init(void)  
  2. {  
  3.         bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);  
  4.         if (!bus_kset)  
  5.                 return -ENOMEM;  
  6.         return 0;  
  7. }  

先看bus_uevent_ops,这是一个uevent的操作集(我也还没清楚uevent的用途,所以uevent的内容先放着)

然后到kset_create_and_add
[cpp] view plain copy
  1. struct kset *kset_create_and_add(const char *name,  
  2.                                  struct kset_uevent_ops *uevent_ops,  
  3.                                  struct kobject *parent_kobj)  
  4. //传递进来的参数为("bus", &bus_uevent_ops, NULL)  
  5. {  
  6.         struct kset *kset;  
  7.         int error;  
  8.   
  9.         //创建一个kset容器  
  10.         kset = kset_create(name, uevent_ops, parent_kobj);  
  11.         if (!kset)  
  12.                 return NULL;  
  13.   
  14.         //注册创建的kset容器  
  15.         error = kset_register(kset);  
  16.         if (error) {  
  17.                 kfree(kset);  
  18.                 return NULL;  
  19.         }  
  20.         return kset;  
  21. }  

首先需要创建一个kset容器
[cpp] view plain copy
  1. static struct kset *kset_create(const char *name,  
  2.                                 struct kset_uevent_ops *uevent_ops,  
  3.                                 struct kobject *parent_kobj)  
  4. //传递进来的参数为("bus", &bus_uevent_ops, NULL)  
  5. {  
  6.         struct kset *kset;  
  7.   
  8.         //为kset分配内存  
  9.         kset = kzalloc(sizeof(*kset), GFP_KERNEL);  
  10.         if (!kset)  
  11.                 return NULL;  
  12.   
  13.         //设置kset中kobject的名字,这里为bus  
  14.         kobject_set_name(&kset->kobj, name);  
  15.   
  16.         //设置uevent操作集,这里为bus_uevent_ops  
  17.         kset->uevent_ops = uevent_ops;  
  18.   
  19.         //设置父对象,这里为NULL  
  20.         kset->kobj.parent = parent_kobj;  
  21.   
  22.         //设置容器操作集  
  23.         kset->kobj.ktype = &kset_ktype;  
  24.   
  25.         //设置父容器  
  26.         kset->kobj.kset = NULL;  
  27.   
  28.         return kset;  
  29. }  

这里的ktype,也就是kset_ktype是一个操作集,用于为sys下文件的实时反馈做服务,例如我们cat name的时候就要通过ktype提供的show函数,具体什么怎么运用,将在后面讲解

现在回到kset_create_and_add中的kset_register,将建立好的kset添加进sys里
[cpp] view plain copy
  1. int kset_register(struct kset *k)  
  2. {  
  3.         int err;  
  4.   
  5.         if (!k)  
  6.                 return -EINVAL;  
  7.   
  8.         //初始化  
  9.         kset_init(k);  
  10.   
  11.         //添加该容器  
  12.         err = kobject_add_internal(&k->kobj);  
  13.         if (err)  
  14.                 return err;  
  15.         kobject_uevent(&k->kobj, KOBJ_ADD);  
  16.         return 0;  
  17. }  

[cpp] view plain copy
  1. //kset_init进行一些固定的初始化操作,里面没有我们需要关心的内容  
  2. //kobject_add_internal为重要的一个函数,他对kset里kobj的从属关系进行解析,搭建正确的架构  
  3.   
  4. static int kobject_add_internal(struct kobject *kobj)  
  5. {  
  6.         int error = 0;  
  7.         struct kobject *parent;  
  8.   
  9.         //检测kobj是否为空  
  10.         if (!kobj)  
  11.                 return -ENOENT;  
  12.   
  13.         //检测kobj名字是否为空  
  14.         if (!kobj->name || !kobj->name[0]) {  
  15.                 pr_debug("kobject: (%p): attempted to be registered with empty "  
  16.                          "name!/n", kobj);  
  17.                 WARN_ON(1);  
  18.                 return -EINVAL;  
  19.         }  
  20.   
  21.         //提取父对象  
  22.         parent = kobject_get(kobj->parent);  
  23.   
  24.         /* join kset if set, use it as parent if we do not already have one */  
  25.         //父容器存在则设置父对象  
  26.         if (kobj->kset) {//在bus的kset中为空,所以不会进入到下面的代码  
  27.   
  28.                 //检测是否已经设置父对象  
  29.                 if (!parent)  
  30.                         //无则使用父容器为父对象  
  31.                         parent = kobject_get(&kobj->kset->kobj);  
  32.   
  33.                 //添加该kobj到父容器的链表中  
  34.                 kobj_kset_join(kobj);  
  35.   
  36.                 //设置父对象  
  37.                 kobj->parent = parent;  
  38.         }  
  39.   
  40.         pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'/n",  
  41.                  kobject_name(kobj), kobj, __func__,  
  42.                  parent ? kobject_name(parent) : "<NULL>",  
  43.                  kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");  
  44.   
  45.         //建立相应的目录  
  46.         error = create_dir(kobj);  
  47.   
  48.         if (error) {  
  49.                 kobj_kset_leave(kobj);  
  50.                 kobject_put(parent);  
  51.                 kobj->parent = NULL;  
  52.   
  53.                 if (error == -EEXIST)  
  54.                         printk(KERN_ERR "%s failed for %s with "  
  55.                                "-EEXIST, don't try to register things with "  
  56.                                "the same name in the same directory./n",  
  57.                                __func__, kobject_name(kobj));  
  58.                 else  
  59.                         printk(KERN_ERR "%s failed for %s (%d)/n",  
  60.                                __func__, kobject_name(kobj), error);  
  61.                 dump_stack();  
  62.         } else  
  63.                 kobj->state_in_sysfs = 1;  
  64.   
  65.         return error;  
  66. }  

至此bus的目录就建立起来了

模型如下
 
接下来是devices,在/drivers/base/core.c里

[cpp] view plain copy
  1. <span style="font-family: Arial; background-color: rgb(255, 255, 255);"></span>  
  2.   
  3. int __init devices_init(void)  
  4. {  
  5.         devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);  
  6.         if (!devices_kset)  
  7.                 return -ENOMEM;  
  8.         return 0;  
  9. }  
过程和bus的注册一致,我就不复述了~
模型如下
 
然后是platform的注册
在platform的注册中,分为两个部分,一部分是注册到devices中,另一部分是注册到bus中,代码在/drivers/base/platform.c中

[cpp] view plain copy
  1. int __init platform_bus_init(void)  
  2. {  
  3.         int error;  
  4.           
  5.         //注册到devices目录中  
  6.         error = device_register(&platform_bus);  
  7.         if (error)  
  8.                 return error;  
  9.   
  10.         //注册到bus目录中  
  11.         error =  bus_register(&platform_bus_type);  
  12.           
  13. if (error)  
  14.                 device_unregister(&platform_bus);  
  15.         return error;  
  16. }  

首先是device_register,注册的参数为platform_bus,如下所示
struct device platform_bus = {
        .bus_id                = "platform",
};
很简单,只有一个参数,表明了目录名
[cpp] view plain copy
  1. int device_register(struct device *dev)  
  2. {  
  3.         //初始化dev结构  
  4.         device_initialize(dev);  
  5.         //添加dev至目录  
  6.         return device_add(dev);  
  7. }  
  8.   
  9. void device_initialize(struct device *dev)  
  10. {  
  11.         //重要的一步,指明了父容器为devices_kset,而devices_kset的注册在前面已经介绍过了  
  12.         dev->kobj.kset = devices_kset;  
  13.         //初始化kobj的ktype为device_ktype  
  14.         kobject_init(&dev->kobj, &device_ktype);  
  15.         klist_init(&dev->klist_children, klist_children_get,  
  16.                    klist_children_put);  
  17.         INIT_LIST_HEAD(&dev->dma_pools);  
  18.         INIT_LIST_HEAD(&dev->node);  
  19.         init_MUTEX(&dev->sem);  
  20.         spin_lock_init(&dev->devres_lock);  
  21.         INIT_LIST_HEAD(&dev->devres_head);  
  22.         device_init_wakeup(dev, 0);  
  23.         set_dev_node(dev, -1);  
  24. }  
  25.   
  26. int device_add(struct device *dev)  
  27. {  
  28.         struct device *parent = NULL;  
  29.         struct class_interface *class_intf;  
  30.         int error;  
  31.   
  32.         dev = get_device(dev);  
  33.         if (!dev || !strlen(dev->bus_id)) {  
  34.                 error = -EINVAL;  
  35.                 goto Done;  
  36.         }  
  37.   
  38.         pr_debug("device: '%s': %s/n", dev->bus_id, __func__);  
  39.   
  40.         parent = get_device(dev->parent);  
  41.         setup_parent(dev, parent);  
  42.   
  43.         if (parent)  
  44.                 set_dev_node(dev, dev_to_node(parent));  
  45.   
  46.         //设置dev->kobj的名字和父对象,并建立相应的目录  
  47.         error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id);  
  48.         if (error)  
  49.                 goto Error;  
  50.   
  51.         if (platform_notify)  
  52.                 platform_notify(dev);  
  53.   
  54.         if (dev->bus)  
  55.                 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  
  56.                                              BUS_NOTIFY_ADD_DEVICE, dev);  
  57.   
  58.         //建立uevent文件  
  59.         error = device_create_file(dev, &uevent_attr);  
  60.         if (error)  
  61.                 goto attrError;  
  62.   
  63.         if (MAJOR(dev->devt)) {  
  64.                 error = device_create_file(dev, &devt_attr);  
  65.                 if (error)  
  66.                         goto ueventattrError;  
  67.         }  
  68.         //建立subsystem连接文件连接到所属class,这里没有设置class对象所以不会建立  
  69.         error = device_add_class_symlinks(dev);  
  70.         if (error)  
  71.                 goto SymlinkError;  
  72.         //建立dev的描述文件,这里没有设置描述文件所以不会建立  
  73.         error = device_add_attrs(dev);  
  74.         if (error)  
  75.                 goto AttrsError;  
  76.         //建立链接文件至所属bus,这里没有设置所属bus所以不会建立  
  77.         error = bus_add_device(dev);  
  78.         if (error)  
  79.                 goto BusError;  
  80.         //添加power文件,因为platform不属于设备,所以不会建立power文件  
  81.         error = device_pm_add(dev);  
  82.         if (error)  
  83.                 goto PMError;  
  84.         kobject_uevent(&dev->kobj, KOBJ_ADD);  
  85.   
  86.         //检测驱动中有无适合的设备进行匹配,但没有设置bus,所以不会进行匹配  
  87.         bus_attach_device(dev);  
  88.         if (parent)  
  89.                 klist_add_tail(&dev->knode_parent, &parent->klist_children);  
  90.   
  91.         if (dev->class) {  
  92.                 down(&dev->class->sem);  
  93.                 list_add_tail(&dev->node, &dev->class->devices);  
  94.   
  95.                 list_for_each_entry(class_intf, &dev->class->interfaces, node)  
  96.                         if (class_intf->add_dev)  
  97.                                 class_intf->add_dev(dev, class_intf);  
  98.                 up(&dev->class->sem);  
  99.         }  
  100. Done:  
  101.         put_device(dev);  
  102.         return error;  
  103. PMError:  
  104.         bus_remove_device(dev);  
  105. BusError:  
  106.         if (dev->bus)  
  107.                 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  
  108.                                              BUS_NOTIFY_DEL_DEVICE, dev);  
  109.         device_remove_attrs(dev);  
  110. AttrsError:  
  111.         device_remove_class_symlinks(dev);  
  112. SymlinkError:  
  113.         if (MAJOR(dev->devt))  
  114.                 device_remove_file(dev, &devt_attr);  
  115. ueventattrError:  
  116.         device_remove_file(dev, &uevent_attr);  
  117. attrError:  
  118.         kobject_uevent(&dev->kobj, KOBJ_REMOVE);  
  119.         kobject_del(&dev->kobj);  
  120. Error:  
  121.         cleanup_device_parent(dev);  
  122.         if (parent)  
  123.                 put_device(parent);  
  124.         goto Done;  
  125. }  
  126.   
  127.   
  128.   
  129. 在kobject_add-> kobject_add_varg-> kobject_add_internal中  
  130.   
  131. //提取父对象,因为没有设置,所以为空  
  132. parent = kobject_get(kobj->parent);  
  133.   
  134. //父容器存在则设置父对象,在前面的dev->kobj.kset = devices_kset中设为了devices_kset  
  135. if (kobj->kset) {  
  136. //检测是否已经设置父对象  
  137.         if (!parent)  
  138.                 //无则使用父容器为父对象  
  139.                 parent = kobject_get(&kobj->kset->kobj);  
  140. //添加该kobj到父容器的链表中  
  141.         kobj_kset_join(kobj);  
  142.   
  143.         //设置父对象  
  144.         kobj->parent = parent;  
  145. }  

现在devices下的platform目录建立好了,模型如下,其中红线描绘了目录关系
现在到bus_register了

注册的参数platform_bus_type如下所示
[cpp] view plain copy
  1. struct bus_type platform_bus_type = {  
  2.         .name                = "platform",  
  3.         .dev_attrs        = platform_dev_attrs,  
  4.         .match                = platform_match,  
  5.         .uevent                = platform_uevent,  
  6.         .suspend                = platform_suspend,  
  7.         .suspend_late        = platform_suspend_late,  
  8.         .resume_early        = platform_resume_early,  
  9.         .resume                = platform_resume,  
  10. };  
  11.   
  12.   
  13. int bus_register(struct bus_type *bus)  
  14. {  
  15.         int retval;  
  16.   
  17.         //声明一个总线私有数据并分配空间  
  18.         struct bus_type_private *priv;  
  19.         priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);  
  20.         if (!priv)  
  21.                 return -ENOMEM;  
  22.   
  23.         //互相关联  
  24.         priv->bus = bus;  
  25.         bus->p = priv;  
  26.   
  27.         BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);  
  28.   
  29.         //设置私有数据中kobj对象的名字  
  30.         retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);  
  31.         if (retval)  
  32.                 goto out;  
  33.   
  34.         //设置父容器为bus_kset,操作集为bus_ktype  
  35.         priv->subsys.kobj.kset = bus_kset;  
  36.         priv->subsys.kobj.ktype = &bus_ktype;  
  37.         priv->drivers_autoprobe = 1;  
  38.   
  39.         //注册bus容器  
  40.         retval = kset_register(&priv->subsys);  
  41.         if (retval)  
  42.                 goto out;  
  43.   
  44.         //建立uevent属性文件  
  45.         retval = bus_create_file(bus, &bus_attr_uevent);  
  46.         if (retval)  
  47.                 goto bus_uevent_fail;  
  48.   
  49.         //建立devices目录  
  50.         priv->devices_kset = kset_create_and_add("devices", NULL,  
  51.                                                  &priv->subsys.kobj);  
  52.         if (!priv->devices_kset) {  
  53.                 retval = -ENOMEM;  
  54.                 goto bus_devices_fail;  
  55.         }  
  56.   
  57.         //建立drivers目录  
  58.         priv->drivers_kset = kset_create_and_add("drivers", NULL,  
  59.                                                  &priv->subsys.kobj);  
  60.         if (!priv->drivers_kset) {  
  61.                 retval = -ENOMEM;  
  62.                 goto bus_drivers_fail;  
  63.         }  
  64.   
  65.         //初始化klist_devices和klist_drivers链表  
  66.         klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);  
  67.         klist_init(&priv->klist_drivers, NULL, NULL);  
  68.   
  69.         //增加probe属性文件  
  70.         retval = add_probe_files(bus);  
  71.         if (retval)  
  72.                 goto bus_probe_files_fail;  
  73.   
  74.         //增加总线的属性文件  
  75.         retval = bus_add_attrs(bus);  
  76.         if (retval)  
  77.                 goto bus_attrs_fail;  
  78.   
  79.         pr_debug("bus: '%s': registered/n", bus->name);  
  80.         return 0;  
  81.   
  82. bus_attrs_fail:  
  83.         remove_probe_files(bus);  
  84. bus_probe_files_fail:  
  85.         kset_unregister(bus->p->drivers_kset);  
  86. bus_drivers_fail:  
  87.         kset_unregister(bus->p->devices_kset);  
  88. bus_devices_fail:  
  89.         bus_remove_file(bus, &bus_attr_uevent);  
  90. bus_uevent_fail:  
  91.         kset_unregister(&bus->p->subsys);  
  92.         kfree(bus->p);  
  93. out:  
  94.         return retval;  
  95. }  
  96.   
  97. 在kset_register-> kobject_add_internal中  
  98.   
  99. //提取父对象,因为没有设置父对象,所以为空  
  100. parent = kobject_get(kobj->parent);  
  101.   
  102. //父容器存在则设置父对象,在上文中设置了父容器priv->subsys.kobj.kset = bus_kset  
  103. if (kobj->kset) {  
  104.   
  105.         //检测是否已经设置父对象  
  106.         if (!parent)  
  107.                 //无则使用父容器为父对象  
  108.                 parent = kobject_get(&kobj->kset->kobj);  
  109.   
  110.         //添加该kobj到父容器的链表中  
  111.         kobj_kset_join(kobj);  
  112.   
  113.         //设置父对象  
  114.         kobj->parent = parent;  
  115. }  

在retval = kset_register(&priv->subsys)完成之后platform在bus下的模型如下图
有印象的话大家还记得在platform下面有两个目录devices和drivers吧~
现在就到这两个目录的注册了
priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);
priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj);
注意这两条语句的头部
priv->devices_kset = kset_create_and_add
priv->drivers_kset = kset_create_and_add
可以清楚的看到bus_type_private下的devices_kset, drivers_kset分别连接到了devices,drivers的kset上
[cpp] view plain copy
  1. //现在来看kset_create_and_add("devices", NULL,&priv->subsys.kobj);  
  2. struct kset *kset_create_and_add(const char *name,  
  3.                                  struct kset_uevent_ops *uevent_ops,  
  4.                                  struct kobject *parent_kobj)  
  5. //参数为"devices", NULL,&priv->subsys.kobj  
  6. {  
  7.         struct kset *kset;  
  8.         int error;  
  9.   
  10.         //创建一个kset容器  
  11.         kset = kset_create(name, uevent_ops, parent_kobj);  
  12.         if (!kset)  
  13.                 return NULL;  
  14.   
  15.         //注册创建的kset容器  
  16.         error = kset_register(kset);  
  17.         if (error) {  
  18.                 kfree(kset);  
  19.                 return NULL;  
  20.         }  
  21.         return kset;  
  22. }  
  23. 在kset_create 中比较重要的操作为  
  24. kset->kobj.ktype = &kset_ktype //设置了ktype,为kset_ktype  
  25. kset->kobj.parent = parent_kobj; //设置了父对象,为priv->subsys.kobj,也就是platform_bus_type->p->subsys.kobj  
  26. kset->kobj.kset = NULL;    //设置父容器为空  
  27. 在kset_register中  
  28.   
  29. //提取父对象  
  30. parent = kobject_get(kobj->parent); //在之前设置为了  
  31.   
  32. //父容器存在则设置父对象,由于父容器为空,不执行以下代码  
  33. if (kobj->kset) {  
  34.   
  35.         //检测是否已经设置父对象  
  36.         if (!parent)  
  37.                 //无则使用父容器为父对象  
  38.                 parent = kobject_get(&kobj->kset->kobj);  
  39.   
  40.         //添加该kobj到父容器的链表中  
  41.         kobj_kset_join(kobj);  
  42.   
  43.         //设置父对象  
  44.         kobj->parent = parent;  
  45. }  

至此, devices的模型就建立好了,drivers模型的建立和devices是一致的,只是名字不同而已,我就不复述了,建立好的模型如下
 
好了~  到了这里,bus,devices和platform的基础模型就就建立好了,就等设备来注册了
在platform模型设备的建立中,需要2个部分的注册,驱动的注册和设备的注册
platform_device_register(&test_device);        
platform_driver_register(&test_driver);
首先看platform_device_register
注册参数为test_device,结构如下
static struct platform_device test_device = {
        .name = "test_ts",
        .id = -1,
        //. resource
        //.dev
};
这个结构主要描述了设备的名字,ID和资源和私有数据,其中资源和私有数据我们在这里不使用,将在别的文章中进行讲解
[cpp] view plain copy
  1. int platform_device_register(struct platform_device *pdev)  
  2. {  
  3.         //设备属性的初始化  
  4.         device_initialize(&pdev->dev);  
  5.         //将设备添加进platform里  
  6.         return platform_device_add(pdev);  
  7. }  
  8.   
  9. void device_initialize(struct device *dev)  
  10. {  
  11.         dev->kobj.kset = devices_kset;                   //设置kset为devices_kset,则将设备挂接上了devices目录  
  12.         kobject_init(&dev->kobj, &device_ktype);                    //初始化kobeject,置ktype为device_ktype  
  13.         klist_init(&dev->klist_children, klist_children_get,  
  14.                    klist_children_put);  
  15.         INIT_LIST_HEAD(&dev->dma_pools);  
  16.         INIT_LIST_HEAD(&dev->node);  
  17.         init_MUTEX(&dev->sem);  
  18.         spin_lock_init(&dev->devres_lock);  
  19.         INIT_LIST_HEAD(&dev->devres_head);  
  20.         device_init_wakeup(dev, 0);  
  21.         set_dev_node(dev, -1);  
  22. }  
  23.   
  24. int platform_device_add(struct platform_device *pdev)  
  25. {  
  26.         int i, ret = 0;  
  27.   
  28.         if (!pdev)  
  29.                 return -EINVAL;  
  30.   
  31.         //检测是否设置了dev中的parent,无则赋为platform_bus  
  32.         if (!pdev->dev.parent)  
  33.                 pdev->dev.parent = &platform_bus;  
  34.   
  35.         //设置dev中的bus为platform_bus_type  
  36.         pdev->dev.bus = &platform_bus_type;  
  37.   
  38.         //检测id,id为-1表明该设备只有一个,用设备名为bus_id  
  39.         //不为1则表明该设备有数个,需要用序号标明bus_id  
  40.         if (pdev->id != -1)  
  41.                 snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name,  
  42.                          pdev->id);  
  43.         else  
  44.                 strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);  
  45.   
  46.         //增加资源到资源树中  
  47.         for (i = 0; i < pdev->num_resources; i++) {  
  48.                 struct resource *p, *r = &pdev->resource;  
  49.   
  50.                 if (r->name == NULL)  
  51.                         r->name = pdev->dev.bus_id;  
  52.   
  53.                 p = r->parent;  
  54.                 if (!p) {  
  55.                         if (r->flags & IORESOURCE_MEM)  
  56.                                 p = &iomem_resource;  
  57.                         else if (r->flags & IORESOURCE_IO)  
  58.                                 p = &ioport_resource;  
  59.                 }  
  60.   
  61.                 if (p && insert_resource(p, r)) {  
  62.                         printk(KERN_ERR "%s: failed to claim resource %d/n",pdev->dev.bus_id, i);  
  63.                         ret = -EBUSY;  
  64.                         goto failed;  
  65.                 }  
  66.         }  
  67.   
  68.         pr_debug("Registering platform device '%s'. Parent at %s/n",pdev->dev.bus_id, pdev->dev.parent->bus_id);  
  69.   
  70.         //添加设备到设备层次中  
  71.         ret = device_add(&pdev->dev);  
  72.         if (ret == 0)  
  73.                 return ret;  
  74.   
  75. failed:  
  76.         while (--i >= 0)  
  77.                 if (pdev->resource.flags & (IORESOURCE_MEM|IORESOURCE_IO))  
  78.                         release_resource(&pdev->resource);  
  79.         return ret;  
  80. }  
  81.   
  82.   
  83.   
  84. int device_add(struct device *dev)  
  85. {  
  86.         struct device *parent = NULL;  
  87.         struct class_interface *class_intf;  
  88.         int error;  
  89.   
  90.         dev = get_device(dev);  
  91.         if (!dev || !strlen(dev->bus_id)) {  
  92.                 error = -EINVAL;  
  93.                 goto Done;  
  94.         }  
  95.   
  96.         pr_debug("device: '%s': %s/n", dev->bus_id, __func__);  
  97.   
  98.         //取得上层device,而dev->parent的赋值是在platform_device_add中的pdev->dev.parent = &platform_bus完成的  
  99.         parent = get_device(dev->parent);  
  100.   
  101.         //以上层devices为准重设dev->kobj.parent  
  102.         setup_parent(dev, parent);  
  103.   
  104.         if (parent)  
  105.                 set_dev_node(dev, dev_to_node(parent));  
  106.   
  107.         //设置dev->kobj的名字和父对象,并建立相应目录  
  108.         error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id);  
  109.         if (error)  
  110.                 goto Error;  
  111.   
  112.         if (platform_notify)  
  113.                 platform_notify(dev);  
  114.   
  115.         //一种新型的通知机制,但是platform中没有设置相应的结构,所以在这里跳过  
  116.         /* notify clients of device entry (new way) */  
  117.         if (dev->bus)  
  118.                 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,BUS_NOTIFY_ADD_DEVICE, dev);  
  119.   
  120.         //建立uevent文件  
  121.         error = device_create_file(dev, &uevent_attr);  
  122.         if (error)  
  123.                 goto attrError;  
  124.   
  125.         //设备有设备号则建立dev文件  
  126.         if (MAJOR(dev->devt)) {  
  127.                 error = device_create_file(dev, &devt_attr);  
  128.                 if (error)  
  129.                         goto ueventattrError;  
  130.         }  
  131.         //建立subsystem连接文件连接到所属class  
  132.         error = device_add_class_symlinks(dev);  
  133.         if (error)  
  134.                 goto SymlinkError;  
  135.         //添加dev的描述文件  
  136.         error = device_add_attrs(dev);  
  137.         if (error)  
  138.                 goto AttrsError;  
  139.         //添加链接文件至所属bus  
  140.         error = bus_add_device(dev);  
  141.         if (error)  
  142.                 goto BusError;  
  143.         //添加power文件  
  144.         error = device_pm_add(dev);  
  145.         if (error)  
  146.                 goto PMError;  
  147.         kobject_uevent(&dev->kobj, KOBJ_ADD);  
  148.   
  149.         //检测驱动中有无适合的设备进行匹配,现在只添加了设备,还没有加载驱动,所以不会进行匹配  
  150.         bus_attach_device(dev);  
  151.         if (parent)  
  152.                 klist_add_tail(&dev->knode_parent, &parent->klist_children);  
  153.   
  154.         if (dev->class) {  
  155.                 down(&dev->class->sem);  
  156.                 list_add_tail(&dev->node, &dev->class->devices);  
  157.   
  158.                 list_for_each_entry(class_intf, &dev->class->interfaces, node)  
  159.                         if (class_intf->add_dev)  
  160.                                 class_intf->add_dev(dev, class_intf);  
  161.                 up(&dev->class->sem);  
  162.         }  
  163. Done:  
  164.         put_device(dev);  
  165.         return error;  
  166. PMError:  
  167.         bus_remove_device(dev);  
  168. BusError:  
  169.         if (dev->bus)  
  170.                 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,BUS_NOTIFY_DEL_DEVICE, dev);  
  171.         device_remove_attrs(dev);  
  172. AttrsError:  
  173.         device_remove_class_symlinks(dev);  
  174. SymlinkError:  
  175.         if (MAJOR(dev->devt))  
  176.                 device_remove_file(dev, &devt_attr);  
  177. ueventattrError:  
  178.         device_remove_file(dev, &uevent_attr);  
  179. attrError:  
  180.         kobject_uevent(&dev->kobj, KOBJ_REMOVE);  
  181.         kobject_del(&dev->kobj);  
  182. Error:  
  183.         cleanup_device_parent(dev);  
  184.         if (parent)  
  185.                 put_device(parent);  
  186.         goto Done;  
  187. }  
  188.   
  189. static void setup_parent(struct device *dev, struct device *parent)  
  190. {  
  191.         struct kobject *kobj;  
  192.         //取得上层device的kobj  
  193.         kobj = get_device_parent(dev, parent);  
  194.         //kobj不为空则重设dev->kobj.parent  
  195.         if (kobj)  
  196.                 dev->kobj.parent = kobj;  
  197. }  
  198.   
  199.   
  200. static struct kobject *get_device_parent(struct device *dev,  
  201.                                          struct device *parent)  
  202. {  
  203.         int retval;  
  204.   
  205.         //因为dev->class为空,所以跳过这段代码  
  206.         if (dev->class) {  
  207.                 struct kobject *kobj = NULL;  
  208.                 struct kobject *parent_kobj;  
  209.                 struct kobject *k;  
  210.   
  211.                 if (parent == NULL)  
  212.                         parent_kobj = virtual_device_parent(dev);  
  213.                 else if (parent->class)  
  214.                         return &parent->kobj;  
  215.                 else  
  216.                         parent_kobj = &parent->kobj;  
  217.   
  218.                 spin_lock(&dev->class->class_dirs.list_lock);  
  219.                 list_for_each_entry(k, &dev->class->class_dirs.list, entry)  
  220.                         if (k->parent == parent_kobj) {  
  221.                                 kobj = kobject_get(k);  
  222.                                 break;  
  223.                         }  
  224.                 spin_unlock(&dev->class->class_dirs.list_lock);  
  225.                 if (kobj)  
  226.                         return kobj;  
  227.   
  228.                 k = kobject_create();  
  229.                 if (!k)  
  230.                         return NULL;  
  231.                 k->kset = &dev->class->class_dirs;  
  232.                 retval = kobject_add(k, parent_kobj, "%s", dev->class->name);  
  233.                 if (retval < 0) {  
  234.                         kobject_put(k);  
  235.                         return NULL;  
  236.                 }  
  237.                 return k;  
  238.         }  
  239.   
  240.         if (parent)  
  241.                 //返回上层device的kobj  
  242.                 return &parent->kobj;  
  243.         return NULL;  
  244. }  
  245.   
  246. 在bus_attach_device中虽然没有成功进行匹配,但是有很重要的一步为之后正确的匹配打下基础  
  247. void bus_attach_device(struct device *dev)  
  248. {  
  249.         struct bus_type *bus = dev->bus;  
  250.         int ret = 0;  
  251.   
  252.         if (bus) {  
  253.                 if (bus->p->drivers_autoprobe)  
  254.                         ret = device_attach(dev);  
  255.                 WARN_ON(ret < 0);  
  256.                 if (ret >= 0)  
  257.                         klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);  
  258.         }  
  259. }  

klist_add_tail(&dev->knode_bus, &bus->p->klist_devices)就是这一行
在这一行代码中将设备挂载到了bus下的devices链表下,这样,当驱动请求匹配的时候,platform总线就会历遍devices链表为驱动寻找合适的设备


现在来看一下test_device的模型
然后platform_driver_unregister,他的参数 test_driver的结构如下
[cpp] view plain copy
  1. 然后platform_driver_unregister,他的参数 test_driver的结构如下  
  2. static struct platform_driver test_driver = {  
  3.         .probe                = test_probe,  
  4.         .remove                = test_remove,  
  5.         .driver                = {  
  6.                 .name        = "test_ts",  
  7.                 .owner        = THIS_MODULE,  
  8.         },  
  9. };  
  10.   
  11. int platform_driver_register(struct platform_driver *drv)  
  12. {  
  13.         drv->driver.bus = &platform_bus_type;  
  14.         if (drv->probe)  
  15.                 drv->driver.probe = platform_drv_probe;  
  16.         if (drv->remove)  
  17.                 drv->driver.remove = platform_drv_remove;  
  18.         if (drv->shutdown)  
  19.                 drv->driver.shutdown = platform_drv_shutdown;  
  20.         if (drv->suspend)  
  21.                 drv->driver.suspend = platform_drv_suspend;  
  22.         if (drv->resume)  
  23.                 drv->driver.resume = platform_drv_resume;  
  24.         return driver_register(&drv->driver);  
  25. }  

从上面代码可以看出,在platform_driver中设置了probe, remove, shutdown, suspend或resume函数的话
则drv->driver也会设置成platform对应的函数
[cpp] view plain copy
  1. int driver_register(struct device_driver *drv)  
  2. {  
  3.         int ret;  
  4.         struct device_driver *other;  
  5.           
  6.         //检测总线的操作函数和驱动的操作函数是否同时存在,同时存在则提示使用总线提供的操作函数  
  7.         if ((drv->bus->probe && drv->probe) ||  
  8.             (drv->bus->remove && drv->remove) ||  
  9.             (drv->bus->shutdown && drv->shutdown))  
  10.                 printk(KERN_WARNING "Driver '%s' needs updating - please use ""bus_type methods/n", drv->name);  
  11.   
  12.         //检测是否已经注册过  
  13.         other = driver_find(drv->name, drv->bus);  
  14.         if (other) {  
  15.                 put_driver(other);  
  16.                 printk(KERN_ERR "Error: Driver '%s' is already registered, “"aborting.../n", drv->name);  
  17.                 return -EEXIST;  
  18.         }  
  19.   
  20.         //添加驱动到总线上  
  21.         ret = bus_add_driver(drv);  
  22.         if (ret)  
  23.                 return ret;  
  24.   
  25.           
  26.         ret = driver_add_groups(drv, drv->groups);  
  27.         if (ret)  
  28.                 bus_remove_driver(drv);  
  29.         return ret;  
  30. }  
  31.   
  32.   
  33.   
  34. int bus_add_driver(struct device_driver *drv)  
  35. {  
  36.         struct bus_type *bus;  
  37.         struct driver_private *priv;  
  38.         int error = 0;  
  39.   
  40.         //取bus结构  
  41.         bus = bus_get(drv->bus);  
  42.         if (!bus)  
  43.                 return -EINVAL;  
  44.   
  45.         pr_debug("bus: '%s': add driver %s/n", bus->name, drv->name);  
  46.   
  47.         //分配驱动私有数据  
  48.         priv = kzalloc(sizeof(*priv), GFP_KERNEL);  
  49.         if (!priv) {  
  50.                 error = -ENOMEM;  
  51.                 goto out_put_bus;  
  52.         }  
  53.   
  54.         //初始化klist_devices链表  
  55.         klist_init(&priv->klist_devices, NULL, NULL);  
  56.   
  57.         //互相关联  
  58.         priv->driver = drv;  
  59.         drv->p = priv;  
  60.   
  61.         //设置私有数据的父容器,在这一步中,设置了kset为platform下的drivers_kset结构,也就是drivers呢个目录  
  62.         priv->kobj.kset = bus->p->drivers_kset;  
  63.   
  64.         //初始化kobj对象,设置容器操作集并建立相应的目录,这里由于没有提供parent,所以会使用父容器中的kobj为父对象  
  65.         error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,  
  66.                                      "%s", drv->name);  
  67.         if (error)  
  68.                 goto out_unregister;  
  69.   
  70.         //检测所属总线的drivers_autoprobe属性是否为真  
  71.         //为真则进行与设备的匹配,到这里,就会与我们之前注册的test_device连接上了,至于如何连接,进行了什么操作,将在别的文章中详细描述  
  72.         if (drv->bus->p->drivers_autoprobe) {  
  73.                 error = driver_attach(drv);  
  74.                 if (error)  
  75.                         goto out_unregister;  
  76.         }  
  77.   
  78.         //挂载到所属总线驱动链表上  
  79.         klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);  
  80.         module_add_driver(drv->owner, drv);  
  81.   
  82.         //建立uevent属性文件  
  83.         error = driver_create_file(drv, &driver_attr_uevent);  
  84.         if (error) {  
  85.                 printk(KERN_ERR "%s: uevent attr (%s) failed/n",  
  86.                         __func__, drv->name);  
  87.         }  
  88.   
  89.         //建立设备属性文件  
  90.         error = driver_add_attrs(bus, drv);  
  91.         if (error) {  
  92.                 printk(KERN_ERR "%s: driver_add_attrs(%s) failed/n",__func__, drv->name);  
  93.         }  
  94.         error = add_bind_files(drv);  
  95.         if (error) {  
  96.                 printk(KERN_ERR "%s: add_bind_files(%s) failed/n",__func__, drv->name);  
  97.         }  
  98.   
  99.         kobject_uevent(&priv->kobj, KOBJ_ADD);  
  100.         return error;  
  101. out_unregister:  
  102.         kobject_put(&priv->kobj);  
  103. out_put_bus:  
  104.         bus_put(bus);  
  105.         return error;  
  106. }  

到这里test_driver的模型就建立好了,图就是最上面的层次图,我就不再贴了

到这里一个基本的框架就建立起来了~
 
下面,我开始对kobject kset和ktype做分析

先说说关系,ktype与kobject和kset这两者之前的关系较少,让我画一个图,是这样的

 

 
ktype依赖于kobject,kset也依赖于kobject,而kobject有时需要kset(所以用了一个白箭头),不一定需要ktype(真可怜,连白箭头都没有)

首先先说一下这个可有可无的ktype

到/sys/bus/platform下面可以看见一个drivers_autoprobe的文件
cat drivers_autoprobe可以查看这个文件的值
echo 0 > drivers_autoprobe则可以改变这个文件的值
drivers_autoprobe这个文件表示的是是否自动进行初始化

[cpp] view plain copy
  1. void bus_attach_device(struct device *dev)  
  2. {  
  3.         struct bus_type *bus = dev->bus;  
  4.         int ret = 0;  
  5.   
  6.         if (bus) {  
  7.                 if (bus->p->drivers_autoprobe)  
  8.                         ret = device_attach(dev);  
  9.                 WARN_ON(ret < 0);  
  10.                 if (ret >= 0)  
  11.                         klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);  
  12.         }  
  13. }  

中可以看见这么一段代码
if (bus->p->drivers_autoprobe)
        ret = device_attach(dev);
bus->p->drivers_autoprobe的值为真则进行匹配
而drivers_autoprobe这个文件则可以动态的修改这个值选择是否进行匹配
使用外部文件修改内核参数,ktype就是提供了这么一种方法

现在让我们看看ktype是怎么通过kobject进行运作的
首先是ktype及通过ktype进行运作的drivers_autoprobe的注册

ktype的挂载十分简单,因为他是和kobject是一体的
只有这么下面一句        
priv->subsys.kobj.ktype = &bus_ktype;
这样就将bus_ktype挂载到了platform_bus_type的kobject上
drivers_autoprobe的注册如下
[cpp] view plain copy
  1. retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);  
  2.   
  3. bus_attr_drivers_autoprobe这个结构由一系列的宏进行组装  
  4. static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,  
  5.                 show_drivers_autoprobe, store_drivers_autoprobe);  
  6.   
  7. #define BUS_ATTR(_name, _mode, _show, _store)        /  
  8. struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)  
  9.   
  10. #define __ATTR(_name,_mode,_show,_store) { /  
  11.         .attr = {.name = __stringify(_name), .mode = _mode },        /  
  12.         .show        = _show,                                        /  
  13.         .store        = _store,                                        /  
  14. }  

最后bus_attr_drivers_autoprobe的模型如下
[cpp] view plain copy
  1. struct bus_attribute  bus_attr_drivers_autoprobe   
  2. {  
  3.         .attr = {  
  4. .name = “drivers_autoprobe”,  
  5. .mode = S_IWUSR | S_IRUGO   
  6. },          
  7.         .show        = show_drivers_autoprobe,                                          
  8.         .store        = store_drivers_autoprobe,                                          
  9.   
  10. }  

进入到bus_create_file中
[cpp] view plain copy
  1. int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)  
  2. //参数为(bus, &bus_attr_drivers_autoprobe)  
  3. {  
  4.         int error;  
  5.         if (bus_get(bus)) {  
  6.                 error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr);  
  7.                 bus_put(bus);  
  8.         } else  
  9.                 error = -EINVAL;  
  10.         return error;  
  11. }  
  12.   
  13. int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)  
  14. //参数为(&bus->p->subsys.kobj, &attr->attr)  
  15. {  
  16.         BUG_ON(!kobj || !kobj->sd || !attr);  
  17.   
  18.         return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);  
  19.   
  20. }  
  21.   
  22. int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,int type)  
  23. //参数为(&bus->p->subsys.kobj ->sd, &attr->attr, SYSFS_KOBJ_ATTR)  
  24. {  
  25.         return sysfs_add_file_mode(dir_sd, attr, type, attr->mode);  
  26. }  
  27.   
  28.   
  29. int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,  
  30.                         const struct attribute *attr, int type, mode_t amode)  
  31. //整理一下参数,现在应该为  
  32. //(&platform_bus_type->p->subsys.kobj ->sd, &bus_attr_drivers_autoprobe->attr, SYSFS_KOBJ_ATTR, &bus_attr_drivers_autoprobe->attr->mode)  
  33. {  
  34.         umode_t mode = (amode & S_IALLUGO) | S_IFREG;  
  35.         struct sysfs_addrm_cxt acxt;  
  36.         struct sysfs_dirent *sd;  
  37.         int rc;  
  38.   
  39.         //在这一步中可以看出新建了一个节点  
  40.         sd = sysfs_new_dirent(attr->name, mode, type);  
  41.         if (!sd)  
  42.                 return -ENOMEM;  
  43.           
  44.         //这一步挂载了&bus_attr_drivers_autoprobe->attr到节点中,为以后提取attr及上层结构做准备  
  45.         sd->s_attr.attr = (void *)attr;  
  46.   
  47.         // dir_sd也就是上层目录,在这里为platform_bus_type->p->subsys.kobj ->sd  
  48.         //也就是/sys/bus/platform这个目录  
  49.         sysfs_addrm_start(&acxt, dir_sd);  
  50.         rc = sysfs_add_one(&acxt, sd);  
  51.         sysfs_addrm_finish(&acxt);  
  52.   
  53.         if (rc)  
  54.                 sysfs_put(sd);  
  55.   
  56.         return rc;  
  57. }  
  58.   
  59.   
  60. struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)  
  61. {  
  62.         char *dup_name = NULL;  
  63.         struct sysfs_dirent *sd;  
  64.   
  65.         if (type & SYSFS_COPY_NAME) {  
  66.                 name = dup_name = kstrdup(name, GFP_KERNEL);  
  67.                 if (!name)  
  68.                         return NULL;  
  69.         }  
  70.   
  71.         sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);  
  72.         if (!sd)  
  73.                 goto err_out1;  
  74.   
  75.         if (sysfs_alloc_ino(&sd->s_ino))  
  76.                 goto err_out2;  
  77.   
  78.         atomic_set(&sd->s_count, 1);  
  79.         atomic_set(&sd->s_active, 0);  
  80.   
  81.         sd->s_name = name;   //节点的名字为&bus_attr_drivers_autoprobe->attr->name  也就是drivers_autoprobe  
  82.         sd->s_mode = mode;  
  83. sd->s_flags = type;   //节点的type为SYSFS_KOBJ_ATTR  
  84.   
  85.   
  86.         return sd;  
  87.   
  88. err_out2:  
  89.         kmem_cache_free(sysfs_dir_cachep, sd);  
  90. err_out1:  
  91.         kfree(dup_name);  
  92.         return NULL;  
  93. }  

现在一切准备就绪,来看看怎么读取吧
首先是open,大概流程可以看我的另一篇文章<从文件到设备>,一直看到ext3_lookup
这里和ext3_lookup不同的是,sys的文件系统是sysfs文件系统,所以应该使用的lookup函数为sysfs_lookup(/fs/sysfs/dir.c)

[cpp] view plain copy
  1. static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,  
  2.                                 struct nameidata *nd)  
  3. {  
  4.         struct dentry *ret = NULL;  
  5.         struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata;  
  6.         struct sysfs_dirent *sd;  
  7.         struct inode *inode;  
  8.   
  9.         mutex_lock(&sysfs_mutex);  
  10.   
  11.         sd = sysfs_find_dirent(parent_sd, dentry->d_name.name);  
  12.   
  13.         if (!sd) {  
  14.                 ret = ERR_PTR(-ENOENT);  
  15.                 goto out_unlock;  
  16.         }  
  17.   
  18.         //节点的初始化在这里  
  19.         inode = sysfs_get_inode(sd);  
  20.         if (!inode) {  
  21.                 ret = ERR_PTR(-ENOMEM);  
  22.                 goto out_unlock;  
  23.         }  
  24.   
  25.         dentry->d_op = &sysfs_dentry_ops;  
  26.         dentry->d_fsdata = sysfs_get(sd);  
  27.         d_instantiate(dentry, inode);  
  28.         d_rehash(dentry);  
  29.   
  30. out_unlock:  
  31.         mutex_unlock(&sysfs_mutex);  
  32.         return ret;  
  33. }  
  34.   
  35.   
  36. struct inode * sysfs_get_inode(struct sysfs_dirent *sd)  
  37. {  
  38.         struct inode *inode;  
  39.   
  40.         inode = iget_locked(sysfs_sb, sd->s_ino);  
  41.         if (inode && (inode->i_state & I_NEW))  
  42.                 //为节点赋值  
  43.                 sysfs_init_inode(sd, inode);  
  44.   
  45.         return inode;  
  46. }  
  47.   
  48.   
  49. static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)  
  50. {  
  51.         struct bin_attribute *bin_attr;  
  52.   
  53.         inode->i_blocks = 0;  
  54.         inode->i_mapping->a_ops = &sysfs_aops;  
  55.         inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;  
  56.         inode->i_op = &sysfs_inode_operations;  
  57.         inode->i_ino = sd->s_ino;  
  58.         lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);  
  59.   
  60.         if (sd->s_iattr) {  
  61.                 set_inode_attr(inode, sd->s_iattr);  
  62.         } else  
  63.                 set_default_inode_attr(inode, sd->s_mode);  
  64.   
  65.         //判断类型  
  66.         switch (sysfs_type(sd)) {  
  67.         case SYSFS_DIR:  
  68.                 inode->i_op = &sysfs_dir_inode_operations;  
  69.                 inode->i_fop = &sysfs_dir_operations;  
  70.                 inode->i_nlink = sysfs_count_nlink(sd);  
  71.                 break;  
  72.         //还记得在注册的时候有一个参数为SYSFS_KOBJ_ATTR赋到了sd->s_flags上面吧  
  73.         case SYSFS_KOBJ_ATTR:  
  74.                 inode->i_size = PAGE_SIZE;  
  75.                 inode->i_fop = &sysfs_file_operations;  
  76.                 break;  
  77.         case SYSFS_KOBJ_BIN_ATTR:  
  78.                 bin_attr = sd->s_bin_attr.bin_attr;  
  79.                 inode->i_size = bin_attr->size;  
  80.                 inode->i_fop = &bin_fops;  
  81.                 break;  
  82.         case SYSFS_KOBJ_LINK:  
  83.                 inode->i_op = &sysfs_symlink_inode_operations;  
  84.                 break;  
  85.         default:  
  86.                 BUG();  
  87.         }  
  88.   
  89.         unlock_new_inode(inode);  
  90. }  
  91.   
  92. sysfs_file_operations的结构如下,之后open和read,write都明了了  
  93.   
  94. const struct file_operations sysfs_file_operations = {  
  95.         .read                = sysfs_read_file,  
  96.         .write                = sysfs_write_file,  
  97.         .llseek                = generic_file_llseek,  
  98.         .open                = sysfs_open_file,  
  99.         .release        = sysfs_release,  
  100.         .poll                = sysfs_poll,  
  101. };  

有关在哪调用open还是请查阅我的另一篇文章<从文件到设备>中 nameidata_to_filp之后的操作

好的~  现在进入到了sysfs_open_file中
[cpp] view plain copy
  1. static int sysfs_open_file(struct inode *inode, struct file *file)  
  2. {  
  3.         struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;  
  4.         //要重的取值,在这里取得了drivers_autoprobe的目录platform的kproject  
  5.         struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;  
  6.         struct sysfs_buffer *buffer;  
  7.         struct sysfs_ops *ops;  
  8.         int error = -EACCES;  
  9.   
  10.         if (!sysfs_get_active_two(attr_sd))  
  11.                 return -ENODEV;  
  12.   
  13.         if (kobj->ktype && kobj->ktype->sysfs_ops)  
  14.                 //这里可谓是ktype实现中的核心,在这里ops设置成了platform_bus_type中kobject->ktype的sysfs_ops  
  15.                 ops = kobj->ktype->sysfs_ops;  
  16.         else {  
  17.                 printk(KERN_ERR "missing sysfs attribute operations for ""kobject: %s/n", kobject_name(kobj));  
  18.                 WARN_ON(1);  
  19.                 goto err_out;  
  20.         }  
  21.   
  22.         if (file->f_mode & FMODE_WRITE) {  
  23.                 if (!(inode->i_mode & S_IWUGO) || !ops->store)  
  24.                         goto err_out;  
  25.         }  
  26.   
  27.         if (file->f_mode & FMODE_READ) {  
  28.                 if (!(inode->i_mode & S_IRUGO) || !ops->show)  
  29.                         goto err_out;  
  30.         }  
  31.   
  32.         error = -ENOMEM;  
  33.         buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);  
  34.         if (!buffer)  
  35.                 goto err_out;  
  36.   
  37.         mutex_init(&buffer->mutex);  
  38.         buffer->needs_read_fill = 1;  
  39.         //然后将设置好的ops挂载到buffer上  
  40.         buffer->ops = ops;  
  41.         //再将buffer挂载到file->private_data中  
  42.         file->private_data = buffer;  
  43.   
  44.         error = sysfs_get_open_dirent(attr_sd, buffer);  
  45.         if (error)  
  46.                 goto err_free;  
  47.   
  48.         sysfs_put_active_two(attr_sd);  
  49.         return 0;  
  50.   
  51. err_free:  
  52.         kfree(buffer);  
  53. err_out:  
  54.         sysfs_put_active_two(attr_sd);  
  55.         return error;  
  56. }  

现在已经为read和write操作准备好了
马上进入到read操作中
 
整个流程如上图所示,如何进入到sysfs_read_file在上面open的操作中已经说明了
我们就从sysfs_read_file开始分析(该文件在/fs/sysfs/file.c中)

[cpp] view plain copy
  1. sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)  
  2. {  
  3.         struct sysfs_buffer * buffer = file->private_data;  
  4.         ssize_t retval = 0;  
  5.   
  6.         mutex_lock(&buffer->mutex);  
  7.         if (buffer->needs_read_fill || *ppos == 0) {  
  8.                 //主要操作在fill_read_buffer中  
  9.                 retval = fill_read_buffer(file->f_path.dentry,buffer);  
  10.                 if (retval)  
  11.                         goto out;  
  12.         }  
  13.         pr_debug("%s: count = %zd, ppos = %lld, buf = %s/n",__func__, count, *ppos, buffer->page);  
  14.         retval = simple_read_from_buffer(buf, count, ppos, buffer->page,  
  15.                                          buffer->count);  
  16. out:  
  17.         mutex_unlock(&buffer->mutex);  
  18.         return retval;  
  19. }  
  20.   
  21. static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)  
  22. {  
  23.         struct sysfs_dirent *attr_sd = dentry->d_fsdata;  
  24.         //取得父目录的kobject,也就是platform的kobject  
  25.         struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;  
  26.         //还记得这个buffer->ops在什么时候进行赋值的么?  
  27.         struct sysfs_ops * ops = buffer->ops;  
  28.         int ret = 0;  
  29.         ssize_t count;  
  30.   
  31.         if (!buffer->page)  
  32.                 buffer->page = (char *) get_zeroed_page(GFP_KERNEL);  
  33.         if (!buffer->page)  
  34.                 return -ENOMEM;  
  35.   
  36.         if (!sysfs_get_active_two(attr_sd))  
  37.                 return -ENODEV;  
  38.   
  39.         buffer->event = atomic_read(&attr_sd->s_attr.open->event);  
  40.   
  41.         //调用ops->show  也就是bus_sysfs_ops->show    具体就是bus_attr_show了  
  42.         //参数为父目录的kobject, bus_attr_drivers_autoprobe->attr,和一段char信息  
  43.         count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);  
  44.   
  45.         sysfs_put_active_two(attr_sd);  
  46.   
  47.         if (count >= (ssize_t)PAGE_SIZE) {  
  48.                 print_symbol("fill_read_buffer: %s returned bad count/n",  
  49.                         (unsigned long)ops->show);  
  50.                 /* Try to struggle along */  
  51.                 count = PAGE_SIZE - 1;  
  52.         }  
  53.         if (count >= 0) {  
  54.                 buffer->needs_read_fill = 0;  
  55.                 buffer->count = count;  
  56.         } else {  
  57.                 ret = count;  
  58.         }  
  59.         return ret;  
  60. }  

现在进入bus_attr_show中

[cpp] view plain copy
  1. static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,char *buf)  
  2. {  
  3.         //提取attr的上层结构,也就是bus_attr_drivers_autoprobe  
  4.         struct bus_attribute *bus_attr = to_bus_attr(attr);  
  5.         //提取kobj的上上层结构,也就是bus_type_private  
  6.         struct bus_type_private *bus_priv = to_bus(kobj);  
  7.         ssize_t ret = 0;  
  8.   
  9.         if (bus_attr->show)  
  10.                 //终于到了这里,最后的调用,调用bus_attr_drivers_autoprobe.show ,也就是show_drivers_autoprobe  
  11.                 //参数为bus_priv->bus,也就是platform_bus_type , 及一段char信息  
  12.                 ret = bus_attr->show(bus_priv->bus, buf);  
  13.         return ret;  
  14. }  
  15.   
  16. static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)  
  17. {  
  18.         return sprintf(buf, "%d/n", bus->p->drivers_autoprobe);  
  19. }  
没什么好介绍了就是打印 buf + bus->p->drivers_autoprobe   从结果来看~ buf是空的
到这里,终于把内核的信息给打印出来了,千辛万苦,层层调用,就是为了取得上层kobject结构,逆运算再取得kobject的上层结构
大家是否对kobject有所了解了呢?~  
在对kobject进行介绍之前  还是先把write操作讲完吧 哈哈~

write操作和read操作重要的步骤基本是一致的,只不过在最后的调用中
[cpp] view plain copy
  1. static ssize_t store_drivers_autoprobe(struct bus_type *bus,  
  2.                                        const char *buf, size_t count)  
  3. {  
  4.         if (buf[0] == '0')  
  5.                 bus->p->drivers_autoprobe = 0;  
  6.         else  
  7.                 bus->p->drivers_autoprobe = 1;  
  8.         return count;  
  9. }  

不进行打印而对内核的参数进行了修改而已

好~ 现在让我们来看看kobject吧

kobject的结构如下

[cpp] view plain copy
  1. struct kobject {  
  2.         const char                *name;          //kobject的名字  
  3.         struct kref                kref;                                //kobject的原子操作  
  4.         struct list_head        entry;  
  5.         struct kobject                *parent;                        //父对象  
  6.         struct kset                *kset;                        //父容器  
  7.         struct kobj_type        *ktype;                        //ktype  
  8.         struct sysfs_dirent        *sd;                                //文件节点  
  9.         unsigned int state_initialized:1;  
  10.         unsigned int state_in_sysfs:1;  
  11.         unsigned int state_add_uevent_sent:1;  
  12.         unsigned int state_remove_uevent_sent:1;  
  13. };  

kobject描述的是较具体的对象,一个设备,一个驱动,一个总线,一类设备

在层次图上可以看出,每个存在于层次图中的设备,驱动,总线,类别都有自己的kobject

kobject与kobject之间的层次由kobject中的parent指针决定

而kset指针则表明了kobject的容器

像platform_bus 和test_device的kset都是devices_kset

呢parent和kset有什么不同呢

我认为是人工和默认的区别,看下面这张图 ,蓝框为kset,红框为kobject
 
 
容器提供了一种默认的层次~  但也可以人工设置层次

对于kobject现在我只理解了这么多,欢迎大家指出有疑问的地方

最后是kset,kset比较简单,看下面的结构
struct kset {
        struct list_head list;
        spinlock_t list_lock;
        struct kobject kobj;
        struct kset_uevent_ops *uevent_ops;
};

对于kset的描述,文档里也有介绍
/**
* struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
*
* A kset defines a group of kobjects.  They can be individually
* different "types" but overall these kobjects all want to be grouped
* together and operated on in the same manner.  ksets are used to
* define the attribute callbacks and other common events that happen to
* a kobject.

翻译过来大概就是
结构kset,一个指定类型的kobject的集合,属于某一个指定的子系统
kset定义了一组kobject,它们可以是不同类型组成但却希望捆在一起有一个统一的操作
kset通常被定义为回调属性和其他通用的事件发生在kobject上

可能翻译的不是很好,望大家见谅
从结构中能看出kset比kobject多了3个属性
list_head                                //列表
spinlock_t                        //共享锁
kset_uevent_ops                //uevent操作集

list_head        连接了所有kobject中kset属性指向自己的kobject
而kset_uevent_ops则用于通知机制,由于uevent的作用我也没接触过,所以暂不解析uevent的机制了


写到这里,不知道大家对内核驱动架构中的注册和对kobject的了解有无加深呢?