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;

}

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


ARM架构下linux设备树加载的方法

ARM架构下linux设备树加载的方法     本文转自:http://www.cnblogs.com/chuncky/p/5000438.html   引入设备树后bootload...
  • liushi558
  • liushi558
  • 2017年02月08日 16:17
  • 612

设备树解析

一、描述         ARM Device Tree起源于OpenFirmware (OF),在过去的Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着...
  • qq_27677015
  • qq_27677015
  • 2016年12月01日 00:13
  • 180

linux 根据设备树注册设备

/platform.c  (1) int of_platform_populate(struct device_node *root, const struct of_device_id *ma...
  • dzw19911024
  • dzw19911024
  • 2017年05月26日 15:22
  • 321

我眼中的Linux设备树(三 属性)

三 属性(property)device_type = "memory"就是一个属性,等号前边是属性,后边是值。节点是一个逻辑上相对独立的实体,属性是用来描述节点特性的,根据需要一个节点由0个,1个或...
  • LoongEmbedded
  • LoongEmbedded
  • 2016年05月19日 14:20
  • 2569

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

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

linux设备树的解释 - 总览

本文系列文章建议参考文章Documentation/devicetree/booting-without-of.txtlinux设备树的解释 - 总览 文章从全局介绍了dt使用的整个流程,言简意赅l...
  • l289123557
  • l289123557
  • 2016年06月29日 16:17
  • 6584

【复习】linux之LED驱动的设备树方式

【前言】感谢陆老师 linux中led驱动(设备树)编程笔记
  • daoshuti
  • daoshuti
  • 2017年01月05日 11:17
  • 1188

ARM Linux 3.x的设备树(Device Tree)--宋宝华

宋宝华 Barry Song 1.    ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称“this w...
  • u014320421
  • u014320421
  • 2016年11月24日 11:34
  • 760

编译设备树

1.编译全部dts make  ARCH=arm  dtbs   DTC工具会自动编译内核中所有的arm类的dts文件生成 dtb文件 2.编译某一个dts ...
  • jack_bro
  • jack_bro
  • 2017年04月13日 09:24
  • 517

建立LINUX开发环境并编译LINUX和UBOOT以及生成设备树过程总结

文件linux-digilent-3.6-digilent-13.01.zip 文件u-boot-digilent-digilent-v2012.04.zip /WORK/Linux_Digile...
  • kobesdu
  • kobesdu
  • 2017年12月27日 19:06
  • 456
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux设备树的建立过程
举报原因:
原因补充:

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