概念:
平台总线只是一种设备模型,其管理的设备本质不变,因此应用访问平台总线上的设备通过/dev这个通道也不会发生改变,只是将设备(符合平台总线设备共性)塞入驱动框架的平台总线来管理,相比字符设备而言只是增加了sys目录下的视图关系。
本章将以平台设备的添加、驱动的注册为切入点,逐步分析总线、平台总线设备的软件层次、组成框架来展示平台总线设备的详情。
应用示例
- 平台备添加设:
static struct platform_device xxx_device = { .name = "xxx", .id = 0, .dev= { .platform_data = xxx_data, }, .num_resources = ARRAY_SIZE(xxx_resources), .resource = xxx_resources, }; platform_device_register(&smsc_lan9217_device);
总线的挂载
- 总线框架
- 总线的初始化
-----itop4412_kernel_3.0/init/main.c----- start_kernel rest_init(); kernel_init(void * unused) do_basic_setup(); ----itop4412_kernel_3.0/drivers/base/init.c----- // /sys下创建class、bus、devices、driver关键子目录、并初始化关键总线 driver_init(); // 依次生成/sys/devices、/sys/dev、/sys/dev/block、/sys/dev/char子目录及相关父kobj(作后续添加节点的根) buses_init(); // 创建一个bus的kset对象,作为后续总线挂载的根节点并生成/sys/bus目录,不再延生,请查看kobject章节 bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); 展开: struct kset *kset_create_and_add(const char *name,const struct kset_uevent_ops *uevent_ops,struct kobject *parent_kobj) name:所需要创建kset的name uevent_ops:uevent操作集 parent_kobj:父节点对象
- 总线的注册:int bus_register(struct bus_type *bus)
- 申请一个总线资源对象,并绑定注入的总线包括总线名
- 将其根节点置为总线初始化所产生的所有总线根对象bus_kset
- 注册该总线至sysfs文件系统,通知用户态在/sys/bus下添加对应的总线目录
- 产生该总线下的devices、drivers目录、对应根节点、对应类型链表用于挂载对应这设备
- 设置总线的属性
- 总结
- 驱动框架模型是建立在kobject、sysfs基础之上,因此最终的操作都要归结至此,总线是属于其中的一个分支也需要满足
- 所有驱动框架实现需要依赖sysfs文件系统,因此该文件系统应该首先被注册
- 总线是虚拟的,并不对应实际的设备,因此总线的初始化并不依赖tmpfs文件系统
- 总线的初始化
- 平台总线的注册流程
-----itop4412_kernel_3.0/init/main.c----- start_kernel vfs_caches_init(totalram_pages) mnt_init(); // sysfs文件系统先初始化,设备模型需要依赖于sysfs文件系统 sysfs_init(); rest_init(); kernel_init(void * unused) do_basic_setup(); // tmpfs文件系统先初始化,设备模型不仅在sys下创建视图,同时也会在/dev下创建用户访问通道,因为其本质上还是设备 init_tmpfs(); // /sys下创建class、bus、devices、driver关键子目录、并初始化关键总线 driver_init(); // 各模块初始化 do_initcalls(); -----itop4412_kernel_3.0/drivers/base/init.c---- driver_init