mkdir and rmdir用途
在configfs中,动态添加或删除某一功能时,可以通过mkdir和rmdir实现
调用流程
当在config目录执行mkdir xxx时,configfs会调ct_group_ops->make_group(group, name),参数group为configfs_subsystem中的su_group, name为mkdir 的第一个参数。
我们需要返回一个struct config_group类型的指针。
数据结构设计
struct test_info {
struct config_group group;
int attr1,
char attr2[8];
};
这里之所以将struct config_group结构体的实体包在一个结构中,而不是使用指针是为了方便通过group成员拿到test_info的内存地址
mkdir实现
static struct config_group *testfs_make(struct config_group *group, const char *name)
{
struct test_info *ti;
ti = kzalloc(sizeof(*ti), GFP_KERNEL);
if (!ti)
return ERR_PTR(-ENOMEM);
return &ti->group;
}
添加以上代码便可在test目录中使用mkdir命令了。但是还有一个问题,这里分配了内存,
但是没有地方释放掉,对于只添加功能,不删除功能好像并没有什么影响。考虑到功能的完整性
还是需要添加的实现。
rmdir实现
rmdir的实现,相较于mkdir就没有那简单了。
通过mkdir创建出来的文件夹,它就是一个子元素,rmdir的操作就是操作这个子元素,所以要实现
rmdir的操作,相当于就是给子元素添加相关的描述。
/*
test_root_release函数中,使用了一个API to_config_group这个API的作用是通过
item拿到group成员的指针,因为这里的item指针实际是struct config_group结构体
中的su_item实体成员,to_config_group()也是一个container_of的封装函数
返回group的指针后,再通过container_of就能拿到在test_make中分配的内存指针。
*/
static void test_root_release(struct config_item *item)
{
struct test_info *ti = container_of(to_config_group(item), struct test_info, group);
kfree(ti);
}
static struct config_item_operations test_root_ops = {
.release = &test_root_release,
};
static struct configfs_attribute *test_root_attrs[] = {
NULL,
};
static struct config_item_type test_root_type = {
.ct_item_ops = &test_root_ops,
.ct_attrs = test_root_attrs,
.ct_owner = THIS_MODULE,
};
添加上以上代码后,再在kzalloc后调用config_group_init_type_name。便实现了rmdir的支持。
config_group_init_type_name(&ti->group, name, &test_root_type);
调用流程
当从用户态调用rmdir之后,首先被调用的是drop_item(testfs_drop函数),在此函数中,我们
并不能直接通过item参数拿到test_info的指针,并kfree掉,这里不能不是不能通过item拿到
test_info的指针,而是不能直接kfree掉,因为在上一层的数据结构中还保存有相关的引用。
这里应该调用config_item_put(item),调用这个函数后,configfs会去掉相关的引用,并调用
item的release函数(test_root_release函数)这时才能kfree掉在make中分配的内存