接下来我们从例子着手

localhost:/home/XX/examples/lddbus#insmod lddbus.ko

此时再看/sys/bus/ 这时就多了一个文件夹ldd。里面的文件构成是这样的

/sys/bus/ldd/

|--device

|--driver

`--version

localhost:/sys/bus/ldd#cat version

$Revision: 1.9$

这表示系统中多了一种名叫ldd的总线类型。同时再看/sys/device/,也多出来一个ldd0的文件夹。这表示系统中多了一个名叫ldd0的硬件。

在lddbus.c中, 定义了一个总线和硬件类型

struct bus_type ldd_bus_type = {

.name = "ldd",

.match = ldd_match,

.hotplug  = ldd_hotplug,

};

struct device ldd_bus = {

.bus_id   = "ldd0",

.release  = ldd_bus_release

};

lddbus模块初始化时调用这个函数

static int __init ldd_bus_init(void)

{

int ret;

ret = bus_register(&ldd_bus_type);

if (ret)

return ret;

if (bus_create_file(&ldd_bus_type, &bus_attr_version))

printk(KERN_NOTICE "Unable to create version attribute/n");

ret = device_register(&ldd_bus);

if (ret)

printk(KERN_NOTICE "Unable to register ldd0/n");

return ret;

}

其实就是调用了两个注册函数,bus_register(), device_register()。bus_create_file()是在sysfs下创建一个文件夹。

bus_register(),向系统注册ldd_bus_type这个总线类型。bus_create_file()这个就是向sysfs中创建一个文件。device_register()系统注册ldd_bus这个硬件类型。

注册好了之后,我们就可以在sysfs下看到相应的信息。

深入讲解,看看bus_register的代码

688 int bus_register(struct bus_type * bus)

689 {

690         int retval;

691

692         retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);

693         if (retval)

694                 goto out;

695

696         subsys_set_kset(bus, bus_subsys);

697         retval = subsystem_register(&bus->subsys);

698         if (retval)

699                 goto out;

700

701         kobject_set_name(&bus->devices.kobj, "devices");

702         bus->devices.subsys = &bus->subsys;

703         retval = kset_register(&bus->devices);

704         if (retval)

705                 goto bus_devices_fail;

706

707         kobject_set_name(&bus->drivers.kobj, "drivers");

708         bus->drivers.subsys = &bus->subsys;

709         bus->drivers.ktype = &ktype_driver;

710         retval = kset_register(&bus->drivers);

711         if (retval)

712                 goto bus_drivers_fail;

713         bus_add_attrs(bus);

714

715         pr_debug("bus type '%s' registered/n", bus->name);

716         return 0;

717

718 bus_drivers_fail:

719         kset_unregister(&bus->devices);

720 bus_devices_fail:

721         subsystem_unregister(&bus->subsys);

722 out:

723         return retval;

724 }

692-700是对bus->subsys的操作。701-705是操作bus->devices。706-710是操作bus->drivers。

692 kobject_set_name()设置bus->subsys.kset.kobj的名字。此函数很简单,就是调用vsnprintf()。此不列出。

696 subsys_set_kset(bus, bus subsys)

#define subsys_set_kset(obj,_subsys)  (obj)->subsys.kset.kobj.kset = &(_subsys).kset

我们先看看bus_subsys的定义,它是一个subsystem类型的全局变量。在driver/base/bus.c中,decl subsys(bus, &ktype bus, NULL); 在/include/linux/kobject.h中有,decl subsys的原型,

#define decl_subsys(_name,_type,_hotplug_ops) /

struct subsystem _name##_subsys = { /

.kset = { /

.kobj = { .name = __stringify(_name) }, /

.ktype = _type, /

.hotplug_ops =_hotplug_ops, /

} /

}

就相当于

struct subsystem bus_subsys = { /

.kset = { /

.kobj = { .name = “bus” }, /

.ktype = ktype_bus, /

.hotplug_ops =NULL, /

} /

}

其中ktype bus定义如下,

static struct kobj_type ktype_bus = {

.sysfs_ops = &bus_sysfs_ops,

};

697 subsystem_register(&bus->subsys)作用是向全局的bus_subsys”登记”, 把自己加入到bus_subsys的链表中去。

subsystem_register() -> kset_add() -> kobject_add()

155 int kobject_add(struct kobject * kobj)

156 {

157         int error = 0;

158         struct kobject * parent;

159

160         if (!(kobj = kobject_get(kobj)))

161                 return -ENOENT;

162         if (!kobj->k_name)

163                 kobj->k_name = kobj->name;

164         parent = kobject_get(kobj->parent);

165

166         pr_debug("kobject %s: registering. parent: %s, set: %s/n",

167                  kobject_name(kobj), parent ? kobject_name(parent) : "",

168                  kobj->kset ? kobj->kset->kobj.name : "" );

169

170         if (kobj->kset) {

171                 down_write(&kobj->kset->subsys->rwsem);

172

173                 if (!parent)

174                         parent = kobject_get(&kobj->kset->kobj);

175

176                 list_add_tail(&kobj->entry,&kobj->kset->list);

177                 up_write(&kobj->kset->subsys->rwsem);

178         }

179         kobj->parent = parent;

180

181         error = create_dir(kobj);

182         if (error) {

183                 /* unlink does the kobject_put() for us */

184                 unlink(kobj);

185                 if (parent)

186                         kobject_put(parent);

187         } else {

188                 kobject_hotplug(kobj, KOBJ_ADD);

189         }

190

191         return error;

192 }

代码的170-178就是把自己连入到父辈上级kset中。我们注意到在kobject_add()函数中181行调用了create_dir(kobj),这个函数作用是在sysfs下创建一个文件夹。可见kobject和sysfs是同时更新的。

kset_register(&bus->devices) 和kset_register(&bus->drivers)作用类似,把bus->devices这个kset加入到bus->subsys这个subsystem中去。最后形成如下的层次结构

lddbus kobject层次结构

同理,我们可以看看device_register()的代码,它也是向devices_subsys这个subsystem注册,最后形成这样的结构与上图类似。

目前为止,我们知道了所谓的xx_register函数,就是通过其内嵌的kobject链入对应的subsystem,或是kset的层次结构中去。这样就可以通过一些全局的变量找到它们了。

转自:http://blog.csdn.net/fudan_abc/article/details/1768384

linux lddbus设备,Linux那些事儿之我是Sysfs(4)举例一lddbus | 技术部落相关推荐

  1. Linux那些事儿之我是Sysfs(4)举例一lddbus

    对了,你得把ldd3的examples代码下下来.不然没法继续了. 接下来我们从例子着手, localhost:/home/XX/examples/lddbus#insmod lddbus.ko 此时 ...

  2. Linux那些事儿之我是Sysfs(5)举例二sculld

    不妨再把sculld的代码也分析一下,先看初始函数 sculld_init()              -> register_ldd_driver()                     ...

  3. linux getdents 例子,Linux那些事儿之我是Sysfs(12)举例三:sysfs读入文件夹内容

    上回我们说到,如何创建文件夹和文件.我们发现,在sysfs中,inode并不那么重要.这是因为我们所要读写的信息已经就在内存中,并且已经形成了层次结构.我们只需有dentry,就可以dentry-&g ...

  4. linux lddbus设备,Linux设备驱动程序学习(14)-Linux设备模型(各环节的整合)

    Linux设备驱动程序学习(14) -Linux设备模型(各环节的整合) 通过一个设备在内核中生命周期的各个阶段,可以更好地理解Linux设备模型.我将通过分析lddbus和sculld的源码来了解L ...

  5. Linux那些事儿之我是Sysfs(1)sysfs初探

    "sysfs is a ram-based filesystem initially based on ramfs. It provides a means to export kernel ...

  6. linux hub设备,Linux设备驱动之USB hub驱动(续)

    5.2.2:接口驱动中的hub_thread()函数 我们之前在分析usb_hub_init()的代码的时候,忽略掉了一部份. 代码片段如下所示: int usb_hub_init(void) { - ...

  7. ()shi linux字符设备,Linux字符设备驱动基础(三)

    Linux字符设备驱动基础(三) 6 创建设备节点 6.1 手动创建设备节点 查看申请的设备名及主设备号: cat /proc/devices # cat /proc/devices Characte ...

  8. linux 杂项设备,Linux下自动创建节点的字符杂项设备 misc_register

    Linux下自动创建节点的字符杂项设备 misc_register admin • 2020 年 01 月 07 日 杂项设备 Linux里面的misc杂项设备是主设备号为10的驱动设备 定义头文件: ...

  9. Linux那些事儿之我是Sysfs(3)设备模型上层容器

    §1 bus 系统中总线由struct bus_type描述,定义为: include/linux/device.h struct bus_type { const char *name;总线类型的名 ...

最新文章

  1. 全国大学生电工数学建模竞赛赛题_A
  2. VTK/ITK 学习资料
  3. flutter图片预览_flutter好用的轮子推荐四-可定制的图片预览查看器photo
  4. 模拟模型学习 几何布朗运动_Java的几何布朗运动
  5. 后缀为frm是什么文件_Shell 点文件可以为你做点什么
  6. UVA 11582 Colossal Fibonacci Numbers!【数学】
  7. python-函数定义
  8. Codeforces 160
  9. 软件工程实验报告1-可行性分析
  10. JESD204B调试4
  11. windows10系统瘦身记
  12. 什么是归纳法、数学归纳法
  13. wz框架登录功能详解——demo1
  14. 八皇后问题(详解带注释)
  15. ​大连商务英百家外语英语六级水平,适合报考BEC中级还是高级
  16. 程序员微信名昵称_微信名字大全
  17. 微信朋友圈技术实现设想
  18. 30亿流量!梨视频靠什么拍出个“短视频世界杯元年”
  19. echarts 柱状图,分别给每个柱子设置不同的颜色
  20. 阿里云IoT投入智物智造战略 三年赋能10亿设备改造10万家数字工厂

热门文章

  1. editplus配置 linux shell 语法高亮 自动补全
  2. 在XP SP3中启用支持NLA的远程桌面
  3. ubuntu系统debootstrap的使用
  4. Bypass WAF:Burp插件绕过一些WAF设备
  5. 如何使用windbg在驱动加载时下断
  6. c语言基本类型学习小结
  7. Linux的文件系统及其硬盘分区挂载原理
  8. Linux Core Dump
  9. 计算机网络本地连接被禁用说明什么,win10系统网络被禁用重新启用本地连接的设置技巧...
  10. mysql select符合查询_数据库select group by 和having语句 多表连接查询 复合查询