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;

}

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


举报

相关文章推荐

linux设备树的建立过程

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

kernel-char设备的建立

分析了一个典型的kernel中的char设备初始化程序,算是kernel下几种设备分析的一个开始吧。

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

linux 设备树

http://blog.csdn.net/21cnbao/article/details/8457546

Linux设备树

宋宝华 Barry Song 1.    ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称“this whole ARM...

linux内核树的建立

本文是参考了网上多篇帖子而写的算不上什么原创。唯一值得欣慰的只不过在本机上实现罢了。因为毕竟失败了几次。也因为本人是初学驱动编程 很多简单的问题在我来说是相当的困难的。望有识之士不要笑话。最后,希望本...

linux内核树的建立

交叉编译驱动环境搭建: 我的开发板是mini2440(s3c2440)内核版本是:2.6.32.2;用开发板自带的源码,利用samba服务器把源代码放到宿主机中,然后解压。(操作的都是...

linux内核树的建立

本文是参考了网上多篇帖子而写的算不上什么原创。唯一值得欣慰的只不过在本机上实现罢了。因为毕竟失败了几次。也因为本人是初学驱动编程 很多简单的问题在我来说是相当的困难的。望有识之士不要笑话。最后,希望本...

LeetCode—二叉树的建立

1.Construct Binary Tree from Inorder and Postorder Traversal Given inorder and postorder traversal...

PAT 1004. Counting Leaves (30)

1004. Counting Leaves (30) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B ...

哈夫曼树

给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。 ...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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