03、注册 group 容器实验
一、注册 group 容器 实验
C
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/configfs.h>
// 定义一个名为"mygroup"的config_group结构体
static struct config_group mygroup;
// 定义一个名为"mygroup_config_item_type"的config_item_type结构体,用于描述配置项类型。
static const struct config_item_type mygroup_config_item_type = {
.ct_owner = THIS_MODULE,
.ct_item_ops = NULL,
.ct_group_ops = NULL,
.ct_attrs = NULL,
};
// 定义名为"myconfig_item_type"的配置项类型结构体
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"); // 模块使用的许可证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
二、源码刨析
这段代码在之前简单configfs子系统的基础上进行了扩展,增加了一个名为"mygroup"的子配置组。下面我将详细解析这段代码的各个部分和工作流程。
2.1、代码结构分析
新增的全局变量
plaintext
static struct config_group mygroup; // 定义一个名为"mygroup"的子配置组
static const struct config_item_type mygroup_config_item_type = {
.ct_owner = THIS_MODULE,
.ct_item_ops = NULL,
.ct_group_ops = NULL,
.ct_attrs = NULL,
};
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- 定义了一个新的配置组
**mygroup**
- 为这个组定义了类型
**mygroup_config_item_type**
,目前也是空实现
修改后的子系统类型定义
plaintext
static const struct config_item_type myconfig_item_type = {
.ct_owner = THIS_MODULE,
.ct_group_ops = NULL, // 注意这里只保留了ct_group_ops
};
1
2
3
4
2
3
4
相比前一版本,这里简化了类型定义,去掉了**ct_item_ops**
和**ct_attrs**
的显式NULL设置
初始化函数的变化
plaintext
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);
// 将子组注册到主系统中
configfs_register_group(&myconfigfs_subsystem.su_group, &mygroup);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
新增了两步操作:
- 使用
**config_group_init_type_name**
初始化子组,指定了名称和类型 - 使用
**configfs_register_group**
将子组注册到主系统中
退出函数
plaintext
static void myconfig_group_exit(void)
{
configfs_unregister_subsystem(&myconfigfs_subsystem);
}
1
2
3
4
2
3
4
退出时只需要注销主子系统,子组会自动被注销
2.2、整体工作流程
模块加载时:
- 初始化主配置组结构(
**myconfigfs_subsystem**
) - 注册主子系统到configfs
- 初始化子配置组
**mygroup**
- 将子组注册到主系统中
- 最终在/sys/config/下会创建如下结构:
- 初始化主配置组结构(
plaintext
/sys/config/myconfigfs/
└── mygroup/
1
2
2
模块存在期间:
- 用户可以通过/sys/config/myconfigfs/和/sys/config/myconfigfs/mygroup/访问配置
- 由于仍然没有定义属性和操作函数,这些组仍然是空的
模块卸载时:
- 内核调用
**myconfig_group_exit()**
函数 - 从configfs注销主子系统
- 整个/sys/config/myconfigfs/目录结构被移除
- 内核调用
2.3、关键点解析
层级结构创建:
- 通过
**configfs_register_group**
可以在子系统中创建子组 - 这种设计允许构建多层次的配置结构
- 通过
自动清理:
- 只需要注销主子系统,子组会自动被清理
- 这是因为configfs维护了父子关系
类型定义的简化:
- 主系统的类型定义中去掉了不必要的NULL赋值
- 子组的类型定义保持了完整形式
命名初始化:
- 使用
**config_group_init_type_name**
可以一次性设置组名和类型 - 比分开设置更方便
- 使用
2.4、实际效果
虽然这个版本增加了子组,但仍然是一个"空壳"实现,因为:
- 没有定义任何可配置属性
- 没有实现任何操作函数
- 没有添加实际业务逻辑
在实际开发中,通常会:
- 为组或项添加属性文件
- 实现操作函数来处理读写
- 构建更复杂的层次结构
- 将配置与实际内核功能关联
这个示例展示了如何在configfs中创建多级配置结构,为构建更复杂的配置系统奠定了基础。