驱动_ConfigFS多级目录操作
ConfigFS 系统实现多级组目录
文章目录
- 前言
- 参考资料
- 一、ConfigFS实现多级目录知识点
- 源码实例
- 源码分析
- 结果分析
- 二、结构体 configfs_group_operations-config_group 再分析
- 三、ConfigFS 多级目录Group和Item 区别和联系
- 定义与角色
- 关键区别
- 联系与协作
- 示例场景
- 内核开发视角
- group和Item 区别小结
- 总结
前言
前面的知识点从ConfigFS
概念 -> ConfigFS
基础必备 ->ConfigFS
注册子系统->ConfigFS
注册group
组->ConfigFS
注册Item
-> ConfigFS
释放资源->再到这里ConfigFS
属性读取->ConfigFS
实现多级目录创建。其实都是从一个简单例子,一步一步到各个知识点,对同一个实例不断添加知识点的功能。 这里就开始理解属性相关知识了。
其实就是要在子group
中继续创建group
实现这样的一个功能或者需求。
参考资料
重温一下前面的知识点,方便后续查看资料时候对知识点进行再一次的脉络梳理:
Linux驱动-设备树插件语法
设备树插件基础必备
设备树插件注册子系统
驱动-设备树插件-注册group
RK3568驱动指南|第八篇 设备树插件-第78章 用户空间创建item实验
驱动-设备数插件-创建Item
设备树插件-第79章 完善drop和release函数实验
驱动-ConfigFS-释放资源篇
设备树插件 注册attribute实验
Linux驱动-ConfigFS-读写属性操作
设备树插件-第81章 实现多级目录实验
迅为设备树插件模块知识点
一、ConfigFS实现多级目录知识点
源码实例
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/configfs.h>// 定义一个名为"mygroup"的config_group结构体
static struct config_group mygroup;// 自定义的配置项结构体
struct myitem
{struct config_item item;int size;void *addr;
};
// 自定义的配置组结构体
struct mygroup
{struct config_group group;
};// 配置项释放函数
void myitem_release(struct config_item *item)
{struct myitem *myitem = container_of(item, struct myitem, item);kfree(myitem);printk("%s\n", __func__);
};// 读取配置项内容的回调函数
ssize_t myread_show(struct config_item *item, char *page)
{struct myitem *myitem = container_of(item, struct myitem, item);memcpy(page, myitem->addr, myitem->size);printk("%s\n", __func__);return myitem->size;
};// 写入配置项内容的回调函数
ssize_t mywrite_store(struct config_item *item, const char *page, size_t size)
{struct myitem *myitem = container_of(item, struct myitem, item);myitem->addr = kmemdup(page, size, GFP_KERNEL);myitem->size = size;printk("%s\n", __func__);return myitem->size;
};// 创建只读配置项
CONFIGFS_ATTR_RO(my, read);
// 创建只写配置项
CONFIGFS_ATTR_WO(my, write);// 配置项属性数组
struct configfs_attribute *my_attrs[] = {&myattr_read,&myattr_write,NULL,
};// 配置项操作结构体
struct configfs_item_operations myitem_ops = {.release = myitem_release,
};// 配置项类型结构体
static struct config_item_type mygroup_item_type = {.ct_owner = THIS_MODULE,.ct_item_ops = &myitem_ops,.ct_attrs = my_attrs,
};// 配置组类型结构体
static struct config_item_type mygroup_type = {.ct_owner = THIS_MODULE,};// 创建配置项函数
struct config_item *mygroup_make_item(struct config_group *group, const char *name)
{struct myitem *myconfig_item;printk("%s\n", __func__);myconfig_item = kzalloc(sizeof(*myconfig_item), GFP_KERNEL);config_item_init_type_name(&myconfig_item->item, name, &mygroup_item_type);return &myconfig_item->item;
}// 删除配置项函数
void mygroup_delete_item(struct config_group *group, struct config_item *item)
{struct myitem *myitem = container_of(item, struct myitem, item);config_item_put(&myitem->item);printk("%s\n", __func__);
}
// 创建配置组函数
struct config_group *mygroup_make_group(struct config_group *group, const char *name)
{struct mygroup *mygroup;printk("%s\n", __func__);mygroup = kzalloc(sizeof(*mygroup), GFP_KERNEL);config_group_init_type_name(&mygroup->group, name, &mygroup_type);return &mygroup->group;
};// 配置组操作结构体
struct configfs_group_operations mygroup_ops = {.make_item = mygroup_make_item,.drop_item = mygroup_delete_item,.make_group = mygroup_make_group,
};// 配置项类型结构体
static const struct config_item_type mygroup_config_item_type = {.ct_owner = THIS_MODULE,.ct_group_ops = &mygroup_ops,
};// 配置项类型结构体
static const struct config_item_type myconfig_item_type = {.ct_owner = THIS_MODULE,.ct_group_ops = NULL,
};// 定义一个configfs_subsystem结构体实例"myconfigfs_subsystem"
static struct configfs_subsystem myconfigfs_subsystem = {.su_group = {.cg_item = {.ci_namebuf = "myconfigfs",.ci_type = &myconfig_item_type,},},
};// 模块的初始化函数
static int myconfig_group_init(void)
{// 初始化配置组config_group_init(&myconfigfs_subsystem.su_group);// 注册子系统configfs_register_subsystem(&myconfigfs_subsystem);// 初始化配置组"mygroup"config_group_init_type_name(&mygroup, "mygroup", &mygroup_config_item_type);// 在子系统中注册配置组"mygroup"configfs_register_group(&myconfigfs_subsystem.su_group, &mygroup);return 0;
}// 模块退出函数
static void myconfig_group_exit(void)
{// 注销子系统configfs_unregister_subsystem(&myconfigfs_subsystem);
}module_init(myconfig_group_init); // 指定模块的初始化函数
module_exit(myconfig_group_exit); // 指定模块的退出函数MODULE_LICENSE("GPL"); // 模块使用的许可证
MODULE_AUTHOR("fangchen"); // 模块的作者
源码分析
为什么对比,每个新知识点都是前面知识点一步一步累加起来的功能、逻辑。 对比看看 方便理解新的知识点。
这里拿ConfigFS
读写属性操作 和 ConfigFS
实现多级目录 案例对比,如下:
我们之前整理过 驱动-设备数插件-创建Item 篇章中 configfs_group_operations
相关知识点
意思就是说:一个配置组也就是(group
) 可以包含多个配置项(item
)和子配置组。 配置项和配置组都是作为配置组的成员存在的。 配置项和配置组之间通过指针进行关联, 以形成一个层次结构。
结果分析
[root@topeet:/sys/kernel/config/myconfigfs/mygroup]# cd test2
[root@topeet:/sys/kernel/config/myconfigfs/mygroup/test2]# ls -l
total 0
-r--r--r-- 1 root root 4096 Oct 17 18:00 read
--w------- 1 root root 4096 Oct 17 18:00 write
[root@topeet:/sys/kernel/config/myconfigfs/mygroup/test2]# mkdir hhh
mkdir: cannot create directory 'hhh': Operation not permitted
[root@topeet:/sys/kernel/config/myconfigfs/mygroup/test2]#
这里在 mygroup
组中创建了Item: test和test2
, 并且在test/test2
中看到创建的属性 read/write
, 那么如何验证可以在Item
创建组group
呢? 那不就是命令 mkdir
内核名 来验证创建组。
上面执行 mkdir hh
就是创建 group
,只是没有权限而已。为什么没有权限,因为我们没有写创建group
的回调方法。
二、结构体 configfs_group_operations-config_group 再分析
对于创建group
前面详解过 驱动-设备树插件-注册group 这里不做详细阐述。
三、ConfigFS 多级目录Group和Item 区别和联系
在 Linux 的 ConfigFS 文件系统中,Group 和 Item 是两种核心对象类型,用于构建动态的、层次化的配置结构。它们的区别和联系如下:
定义与角色
Group(组)
是一个容器对象,用于组织和管理其他 Group 或 Item。
类似于目录,可以包含子目录或文件。
通常表示一个逻辑分组或功能模块(如存储设备的后端、网络服务的配置组等)。
Item(项)
- 是一个叶子对象,代表具体的配置实体。
- 类似于文件,存储实际的配置属性(如参数、状态等)。
- 不能包含其他对象,是配置树中的终端节点。
关键区别
特性 | Group | Item |
---|---|---|
用途 | 组织层次结构(容器) | 存储具体配置(叶子节点) |
能否包含子对象 | 可以包含子 Group 或 Item | 不能包含子对象 |
生命周期 | 通常由内核模块预先定义 | 动态创建/删除(用户可操作) |
操作接口 | 提供 mkdir/rmdir 操作 | 提供属性文件(读写配置值) |
联系与协作
层次关系
ConfigFS 通过 Group 和 Item 构建树形结构:
/config/├── group1/ # Group│ ├── item1 # Item│ └── subgroup/ # Group│ └── item2 # Item└── group2/ # Group└── item3 # Item
Group 是分支节点,Item 是叶子节点。
动态性
Group 通常由内核模块在初始化时注册(如 configfs_register_subsystem)。
Item 由用户通过 mkdir 在 Group 下动态创建(触发内核回调函数分配资源)。
属性交互
Group 可能包含默认属性(如描述信息)。
Item 的属性文件(如 param1、status)允许用户读写具体配置。
示例场景
假设实现一个虚拟存储设备的配置:
/config/target/├── core/ # Group(核心配置)│ └── enable # Item(开关属性)└── storage/ # Group(存储后端)├── fileio/ # Group(文件后端)│ ├── create # Item(创建存储)│ └── path # Item(路径配置)└── block/ # Group(块设备后端)└── dev # Item(设备名)
- target/、storage/ 是 Group,用于分类。
- enable、path、dev 是 Item,存储具体值。
内核开发视角
Group
需实现 struct config_group_type,定义其子对象类型(通过 ct_group_ops 和 ct_item_ops)。
Item
需实现 struct config_item_type,定义属性操作(如 show/store 方法)。
group和Item 区别小结
- Group 是目录结构的骨架,Item 是配置数据的载体。
- 用户通过操作 Group 创建层次,通过 Item 读写配置。
- 两者协同实现动态、可扩展的配置管理,常见于虚拟化、存储(如 LIO Target)、网络等子系统。
总结
- 理解组
group
创建子组group
方案,通过结构体configfs_group_operations
配置实现 - 前面从设备数插件基本知识到子系统创建、组 Item创建、创建属性、子组创建,知识点都是一环套一环,每个知识点不难,但是得形成体系才行。