linux设备树的建立过程

转载 2013年12月06日 09:32:50

为了阐明表示总线、设备和设备驱动程序的各个数据结构之间彼此的关联,它们的注册过程是很有必要的。顺序一定是如下:(1)注册总线---bus_register;(2)注册设备device_register;(3)注册设备驱动程序----bus_add_driver。

下文摘自:点击打开链接

   现在我们得费劲心思的捋一遍我们的驱动注册代码,以便找到设备树添加的关键部分。我想我又得强调一下,我的介绍是SDIO驱动,所以请大家看着 linux内核代码drivers/mmc中关于sdio的驱动来理解我下面的笔记中的内容(想不看内核代码就理解设备树,我想太难太难)
    有关 sbi_register 函数(这是在我的wlan驱动代码中的函数,并不需要你太多的关注 )中sdio_register_driver函数(从现在开始就都是内核函数了) 注册驱动的介绍,在 sdio_register_driver 中将会指明驱动的名称(这里是 wlan_sdio ” ),此函数的参数为 sdio_driver 结构。 驱动所挂接的总线 sdio_bus_type ,其结构类型为:
  static struct bus_type sdio_bus_type = {
             .name             = "sdio",                 // 总线类型
             .dev_attrs       = sdio_dev_attrs,              // 属性
             .match           = sdio_bus_match,         //ops
             .uevent           = sdio_bus_uevent,
             .probe            = sdio_bus_probe,  
             .remove          = sdio_bus_remove,
};
    这个结构将在 sdio_register_driver 函数中被赋值以产生 device_driver 结构。也就是说 device_driver 被包含在 sdio_driver 中。 随后调用函数 driver_register ,其参数为 device_driver (此结构中定义了 bus_type,也就是驱动挂接的总线类型 )。至此将转入所有驱动(不止是 sdio 卡驱动)的注册代码中。此时的驱动结构已经变为device_drive ( 内核定义的驱动结构 ) 
    driver_register 将会完成挂接驱动至总线及生成设备树的过程,其完成的任务大致包括:
    1 、设置设备驱动中 kobject 的名字
     2 、将 kobject 添加至 sysfs 中,也就是在 sysfs 树中创建一个目录( kobject 中有一个函数 create_dir 用于创建目录。)
      3 、调用 driver_attach 函数完成 probe 
      4 、 driver_create_file 创建文件属性,会生成一个属性为 driver_attr_uevent 的属性文件。
      5 、 add_bind_files 生成属性为 driver_attr_unbind 和 driver_attr_bind 的属性文件,关于文件的属性,它定义了文件的读写方式。
     如此抽象的描述及流水账般的记述我发现还是很没有说服力,因此我决定给出一个具体的例子,并给出代码的实现。先看例子——让我们看一下 /sys/bus/ 下的目录,然后来个具体的描述:已知我们的总线的目录名字为”sdio” 。也就是说在 /sys/bus 目录下有一个目录叫 sdio ,即 /sys/bus/sdio 。它是怎么形成的?内核中有”sdio” 总线的驱动,找到这个函数 bus_register (&sdio_bus_type ) ;就是用来注册总线的。我们在前面不也看到了 driver_register 函数吗,是的,你猜对了,还有一个函数叫 device_register 。在这个函数调用完成后,就会得到 /sys/bus/ 目录下的 sdio 目录了。那么驱动的名字 ”wlan_sdio” 又是如何插入到/sys/bus/drivers/wlan_sdio 目录下的呢。在 driver_register->driver_register->bus_add_driver 函数中有个重要的语句 drv->kobj.kset = &bus->drivers ; 想象一下我们折腾了那么长时间的 kobject 与 kset 的意义,是的,这里就是将 driver 的 kobj 所属的 kset 挂接上总线的 kset 。我们这里显得很绕对吗?幸运的是我在网上找到了一个非常棒的示意图:
 
                     
 

   我该怎么样来形容这个图呢? 它把依赖关系说的已经足够清楚了!!我这里唯一要解释的仅仅是在驱动文件夹被正确后所谓的文件属性有在那里。同样我们顺着目录 /sys/bus/sdio/driver/wlan_sdio/ 下我们发现了 bind unbind 和 new_id 三个文件。

   好了,别忘了我们在前面提过的问题,kset 是如何扮演容器的角色的呢?图中很清楚吧,看看粉红色的箭头,kset children list用来将将同类型的kobject连接起来以达到容器的效果。

但是我们的驱动还没有结束,关于这个图的建立,我们势必要用代码才能说得明白。

        我们还是花费一点时间来看一下内核中的代码,关于 sdio 总线注册的代码部分,其它的部分,大家类举就可以了。懂了这段自然就懂了全部:

int bus_register( struct bus_type * bus)

{

       int retval;

 

       BLOCKING_INIT_NOTIFIER_HEAD (&bus->bus_notifier);

 

       retval = kobject_set_name(&bus->subsys.kobj, "%s", bus->name);     // 总线的名字 ”sdio”, 我们说过了一个 kobject对应一个目录,这时会为这个目录赋值名字。

       if (retval)

              goto out;

 

       bus->subsys.kobj.kset = &bus_subsys;                         // 将其 kset 指向 bus_subsys., 如何理解? 看看ldd_bus_type 指向 bus_subsys 的那条蓝线

 

       retval = subsystem_register(&bus->subsys);               //bus->subsys 的注册,实际上是用 kset 指针将其链接在一起。好吧 我得承认实际上这里取消了 subsysem 结构的概念,用 kset 代替了。这里会创建一个目录。它是一个 kset 也是一个 kobject,因为 kset 包含了 kobject 

       if (retval)

              goto out;

 

       retval = bus_create_file(bus, &bus_attr_uevent);             // 创建属性文件

       if (retval)

              goto bus_uevent_fail;

 

       kobject_set_name(&bus->devices.kobj, "devices");          // 设置 devices kset 的名字为 devices

       bus->devices.kobj.parent = &bus->subsys.kobj;            // 参见 ldd_bus_type->devices 指向 ldd_bus_type->sub_sys的红色箭头(注意这里也不是 subsystem, 而是 kset 

       retval = kset_register(&bus->devices);                 // 创建 devices 命名的目录

       if (retval)

              goto bus_devices_fail;

 

       kobject_set_name(&bus->drivers.kobj, "drivers");       // 设置 devices kset 的名字为 drivers

       bus->drivers.kobj.parent = &bus->subsys.kobj;         // 同样参见 ldd_bus_type->drivers 指向 ldd_bus_type->sub_sys的红色箭头(注意这里也不是 subsystem, 而是 kset )。

       bus->drivers.ktype = &driver_ktype;                     //  kobject 默认属性的赋值

       retval = kset_register(&bus->drivers);                  // 创建 drivers 命名的目录

       if (retval)

              goto bus_drivers_fail;

 

       klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);     //klist 结构的初始化,关于 klist 链接的作用我们已经说得很清楚了

       klist_init(&bus->klist_drivers, NULL, NULL);

 

       bus->drivers_autoprobe = 1;

       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 type '%s' registered/n", bus->name);

       return 0;

 

bus_attrs_fail :

       remove_probe_files(bus);

bus_probe_files_fail :

       kset_unregister(&bus->drivers);

bus_drivers_fail :

       kset_unregister(&bus->devices);

bus_devices_fail :

       bus_remove_file(bus, &bus_attr_uevent);

bus_uevent_fail :

       subsystem_unregister(&bus->subsys);

out :

       return retval;

}

至此 我们终于理顺了整个过程。


相关文章推荐

ZYNQ平台学习--(4)设备树生成

Device Tree是一种描述硬件的数据结构,由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的name和value。在Device...

设备树历史最详解

由于内核版本的演变,设备树成了任何使用较高版本linux系统的设备平台所必须文件...

我眼中的Linux设备树(六 memory&chosen节点)

六 memory&chosen节点根节点那一节我们说过,最简单的设备树也必须包含cpus节点和memory节点。memory节点用来描述硬件内存布局的。如果有多块内存,既可以通过多个memory节点表...

Linux内核选配编译步骤

本文主要介绍了Linux内核的选配编译过程,并加入dm9000网卡驱动,通过nfs挂载根文件系统。由于本人为初学者,这是我的一篇学习笔记,有错误或不足之处还望您提出宝贵的建议。...

linux设备树的建立过程

为了阐明表示总线、设备和设备驱动程序的各个数据结构之间彼此的关联,它们的注册过程是很有必要的。顺序一定是如下:(1)注册总线---bus_register;(2)注册设备device_register...

Linux内核移植 part2:uboot设备树--生成过程分析

本文从设备树软件控制相关代码进行分析,进而理清设备树相关的知识。先放一个设备树在内存中的结构图:分析来源为$(tree)/lib/fdtdec_test.c一、数据结构文件头每个dtb都包含如下结构的...
  • abcamus
  • abcamus
  • 2016年12月27日 16:09
  • 980

Linux解析设备树生成设备的过程

设备树的populate过程大致有如下几个阶段 一、根据设备树创建device node链表 start_kernel ---> setup_arch ---> ...

ZedBoard学习手记(四)为使用Linux系统做准备——建立Bootloader及设备树

原文地址:http://www.eefocus.com/nightseas/blog/12-11/287883_2d158.html#articletop 在上一篇博文中,我已经介绍了建立AXI总线...
  • avrmcu1
  • avrmcu1
  • 2014年03月31日 15:45
  • 896

设备树加载过程

  • 2017年11月04日 10:25
  • 100KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux设备树的建立过程
举报原因:
原因补充:

(最多只允许输入30个字)