一、什么是configfs
config_group作为幕后主使,是不轻易出现在台前的。所以有了94行的struct config_item来表现为一个目录。
84行为属性操作方法,操作对象是86行属性。
创建一个结构体包含了configfs子系统,两个属性showme, storeme放在了这里。
142行,定义目录名称。
133行,属性操作定义在128行和129行,这两个函数又是由126行宏定义的。126行宏依赖一个函数to_##_item,其中_item是宏的传入参数,这个函数的作用是从struct config_item转换到第49行的结构,然后作为函数show_attribute和store_attribute的传入参数。
416-417行,初始化子系统。
接着定义config_item_type,
298行,定义了子系统根目录属性操作,跟示例1类似
225行,定义了config_item_type。
转载请注原出处:http://blog.csdn.net/liumangxiong
是一种基于ram的文件系统
二、configfs有什么用处
在用户空间配置内核对象
三、configfs VS ioctl
configfs可直接察看,通过用户态目录文件访问接口,适用于内核对象有众多复杂的配置。
四、configs VS sysfs
configfs可以在用户态创建和删除内核对象。
五、什么时候用configfs
当内核需要很多参数需要配置时;当需要动态创建内核对象并且内核对象需要修改配置时;
不想写用户态程序和ioctl时,写shell脚本就可以直接配置configfs。
六、怎么知道系统上是否已经安装了configfs,安装在哪个目录
执行如下命令,可以看到安装目录为/sys/kernel/config
cat /proc/mounts | grep configfs
configfs /sys/kernel/config configfs rw,relatime 0 0
七、configfs组织结构是怎么样的
顶层结构是struct configfs_subsystem,为configfs子系统结构,接着是struct config_group,是configfs目录和属性的容器,struct config_item是configfs目录,代表可配置的内核对象,struct configfs_attribute是目录下面的属性。
八、代码示例(来自内核目录Documentation\filesystems\configfs)
介绍代码之前,先过一下基本的数据结构:
- 240struct configfs_subsystem {
- 241 struct config_group su_group;
- 242 struct mutex su_mutex;
- 243};
configfs子系统,config_group是抽象容器,之所以叫容器,是因为容器中可以包括config_item,还可以递归包含config_group。struct mutex是用于子系统访问控制的。
- 89/**
- 90 * group - a group of config_items of a specific type, belonging
- 91 * to a specific subsystem.
- 92 */
- 93struct config_group {
- 94 struct config_item cg_item;
- 95 struct list_head cg_children;
- 96 struct configfs_subsystem *cg_subsys;
- 97 struct config_group **default_groups;
- 98};
config_group作为幕后主使,是不轻易出现在台前的。所以有了94行的struct config_item来表现为一个目录。
- 56struct config_item {
- 57 char *ci_name;
- 58 char ci_namebuf[CONFIGFS_ITEM_NAME_LEN];
- 59 struct kref ci_kref;
- 60 struct list_head ci_entry;
- 61 struct config_item *ci_parent;
- 62 struct config_group *ci_group;
- 63 struct config_item_type *ci_type;
- 64 struct dentry *ci_dentry;
- 65};
58行为目录名称。
63行为目录下属性和属性操作,属性表现为目录下的文本文件。
- 82struct config_item_type {
- 83 struct module *ct_owner;
- 84 struct configfs_item_operations *ct_item_ops;
- 85 struct configfs_group_operations *ct_group_ops;
- 86 struct configfs_attribute **ct_attrs;
- 87};
84行为属性操作方法,操作对象是86行属性。
85行为目录操作方法,可以在当前目录下创建item或group。
86行为当前目录属性数组。
- 124struct configfs_attribute {
- 125 const char *ca_name;
- 126 struct module *ca_owner;
- 127 umode_t ca_mode;
- 128};
属性非常简单,有属性名称、所属模块和访问权限。
示例1:创建一个最简单的configfs目录和可读写的属性
创建目录01-childless,下面有三个属性,其中属性storeme为可写。
# ll /sys/kernel/config/01-childless/
-r--r--r--. 1 root root 4096 Sep 27 05:16 description
-r--r--r--. 1 root root 4096 Sep 27 05:16 showme
-rw-r--r--. 1 root root 4096 Sep 27 05:16 storeme
-r--r--r--. 1 root root 4096 Sep 27 05:16 description
-r--r--r--. 1 root root 4096 Sep 27 05:16 showme
-rw-r--r--. 1 root root 4096 Sep 27 05:16 storeme
- 37/*
- 38 * 01-childless
- 39 *
- 40 * This first example is a childless subsystem. It cannot create
- 41 * any config_items. It just has attributes.
- 42 *
- 43 * Note that we are enclosing the configfs_subsystem inside a container.
- 44 * This is not necessary if a subsystem has no attributes directly
- 45 * on the subsystem. See the next example, 02-simple-children, for
- 46 * such a subsystem.
- 47 */
- 48
- 49struct childless {
- 50 struct configfs_subsystem subsys;
- 51 int showme;
- 52 int storeme;
- 53};
创建一个结构体包含了configfs子系统,两个属性showme, storeme放在了这里。
虽然注释里说明了为什么把这两个属性放这里,但还是没太理解,既然属性description可以放子系统下,为什么其他两个属性不行呢?有谁知道的告知一下。
子系统定义如下:
- 138static struct childless childless_subsys = {
- 139 .subsys = {
- 140 .su_group = {
- 141 .cg_item = {
- 142 .ci_namebuf = "01-childless",
- 143 .ci_type = &childless_type,
- 144 },
- 145 },
- 146 },
- 147};
142行,定义目录名称。
143行,定义属性和操作。
接着看属性和操作的定义:
- 114CHILDLESS_ATTR_RO(showme, childless_showme_read);
- 115CHILDLESS_ATTR(storeme, S_IRUGO | S_IWUSR, childless_storeme_read,
- 116 childless_storeme_write);
- 117CHILDLESS_ATTR_RO(description, childless_description_read);
- 118
- 119static struct configfs_attribute *childless_attrs[] = {
- 120 &childless_attr_showme.attr,
- 121 &childless_attr_storeme.attr,
- 122 &childless_attr_description.attr,
- 123 NULL,
- 124};
- 125
- 126CONFIGFS_ATTR_OPS(childless);
- 127static struct configfs_item_operations childless_item_ops = {
- 128 .show_attribute = childless_attr_show,
- 129 .store_attribute = childless_attr_store,
- 130};
- 131
- 132static struct config_item_type childless_type = {
- 133 .ct_item_ops = &childless_item_ops,
- 134 .ct_attrs = childless_attrs,
- 135 .ct_owner = THIS_MODULE,
- 136};
133行,属性操作定义在128行和129行,这两个函数又是由126行宏定义的。126行宏依赖一个函数to_##_item,其中_item是宏的传入参数,这个函数的作用是从struct config_item转换到第49行的结构,然后作为函数show_attribute和store_attribute的传入参数。
134行,关联了属性数组,属性数组在119行定义,第120-122行属性又分别在114-117行定义。
一切准备就绪之后,在模块初始化地方调用子系统注册函数之后,就可以在/sys/kernel/config/下看到创建了子系统了。
- 407static int __init configfs_example_init(void)
- 408{
- 409 int ret;
- 410 int i;
- 411 struct configfs_subsystem *subsys;
- 412
- 413 for (i = 0; example_subsys[i]; i++) {
- 414 subsys = example_subsys[i];
- 415
- 416 config_group_init(&subsys->su_group);
- 417 mutex_init(&subsys->su_mutex);
- 418 ret = configfs_register_subsystem(subsys);
- 419 if (ret) {
- 420 printk(KERN_ERR "Error %d while registering subsystem %s\n",
- 421 ret,
- 422 subsys->su_group.cg_item.ci_namebuf);
- 423 goto out_unregister;
- 424 }
- 425 }
- 426
- 427 return 0;
416-417行,初始化子系统。
418行,注册子系统。
这里做个小结:
1、创建子系统struct configfs_subsystem
2、创建子系统下config_item_type,对应位置configfs_subsystem->config_group->config_item->config_item_type
3、创建config_item_type对应的属性数组和操作,操作主要是show_attribute和store_attribute
4、注册子系统configfs_register_subsystem
示例2:创建一个configfs目录,用户空间可创建目录(新的内核对象)
首先是定义configfs子系统,
- 304static struct configfs_subsystem simple_children_subsys = {
- 305 .su_group = {
- 306 .cg_item = {
- 307 .ci_namebuf = "02-simple-children",
- 308 .ci_type = &simple_children_type,
- 309 },
- 310 },
- 311};
接着定义config_item_type,
- 289/*
- 290 * Note that, since no extra work is required on ->drop_item(),
- 291 * no ->drop_item() is provided.
- 292 */
- 293static struct configfs_group_operations simple_children_group_ops = {
- 294 .make_item = simple_children_make_item,
- 295};
- 296
- 297static struct config_item_type simple_children_type = {
- 298 .ct_item_ops = &simple_children_item_ops,
- 299 .ct_group_ops = &simple_children_group_ops,
- 300 .ct_attrs = simple_children_attrs,
- 301 .ct_owner = THIS_MODULE,
- 302};
298行,定义了子系统根目录属性操作,跟示例1类似
300行,定义了子系统根目录属性,跟示例1类似
299行,这里新增加了configfs_group_operations,具体定义在293行,继续跟进294行函数simple_children_make_item
- 232struct simple_children {
- 233 struct config_group group;
- 234};
- 235
- 236static inline struct simple_children *to_simple_children(struct config_item *item)
- 237{
- 238 return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
- 239}
- 240
- 241static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
- 242{
- 243 struct simple_child *simple_child;
- 244
- 245 simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
- 246 if (!simple_child)
- 247 return ERR_PTR(-ENOMEM);
- 248
- 249 config_item_init_type_name(&simple_child->item, name,
- 250 &simple_child_type);
- 251
- 252 simple_child->storeme = 0;
- 253
- 254 return &simple_child->item;
- 255}
241行,定义了configfs_group_operations->make_item操作,返回值是新创建的struct config_item,传入参数是struct config_group,即是指定config_group下创建config_item项,这就意味着在该子系统(i.e /sys/kernel/config/02-simple-children)下执行命令mkdir,最终会执行到这个函数。
那执行mkdir 之后,会生成一个怎样的新目录呢?
249行,当调用mkdir时,这时就调用config_item_init_type_name初始化这个config_item,接着看250行的simple_child_type到底定义了怎么一个item类型?
- 171static struct configfs_attribute simple_child_attr_storeme = {
- 172 .ca_owner = THIS_MODULE,
- 173 .ca_name = "storeme",
- 174 .ca_mode = S_IRUGO | S_IWUSR,
- 175};
- 176
- 177static struct configfs_attribute *simple_child_attrs[] = {
- 178 &simple_child_attr_storeme,
- 179 NULL,
- 180};
- 219static struct configfs_item_operations simple_child_item_ops = {
- 220 .release = simple_child_release,
- 221 .show_attribute = simple_child_attr_show,
- 222 .store_attribute = simple_child_attr_store,
- 223};
- 224
- 225static struct config_item_type simple_child_type = {
- 226 .ct_item_ops = &simple_child_item_ops,
- 227 .ct_attrs = simple_child_attrs,
- 228 .ct_owner = THIS_MODULE,
- 229};
225行,定义了config_item_type。
227行,先看属性,simple_child_attrs定义在177行,只有一个属性,这个属性定义在171行,仔细看一下这个属性,有可读写的。
所以经过mkdir之后,该目录下就自动生成一个名字为storeme的属性,其对应的操作定义在219行。具体如下:
# cd /sys/kernel/config/02-simple-children/
# ls
description
# ls
description
# mkdir test
# ll
-r--r--r--. 1 root root 4096 Sep 28 21:24 description
drwxr-xr-x. 2 root root 0 Sep 28 21:24 test
# tree
.
|-- description
`-- test
`-- storeme
1 directory, 2 files
-r--r--r--. 1 root root 4096 Sep 28 21:24 description
drwxr-xr-x. 2 root root 0 Sep 28 21:24 test
# tree
.
|-- description
`-- test
`-- storeme
1 directory, 2 files
# cat test/storeme
0
# echo 1 > test/storeme
# cat test/storeme
1
0
# echo 1 > test/storeme
# cat test/storeme
1
示例3:创建group
之前我们讲过,config_group是可以嵌套的,那么现在就来看一下嵌套之后是什么样的:
# cd /sys/kernel/config/03-group-children/
# ls
description
# ls
description
# mkdir test
# mkdir test/test1
# mkdir test/test2
# mkdir test/test3
# tree
.
|-- description
`-- test
|-- description
|-- test1
| `-- storeme
|-- test2
| `-- storeme
`-- test3
`-- storeme
.
|-- description
`-- test
|-- description
|-- test1
| `-- storeme
|-- test2
| `-- storeme
`-- test3
`-- storeme
看出与示例2的区别了吗?
首先看子系统定义
- 382static struct configfs_subsystem group_children_subsys = {
- 383 .su_group = {
- 384 .cg_item = {
- 385 .ci_namebuf = "03-group-children",
- 386 .ci_type = &group_children_type,
- 387 },
- 388 },
- 389};
386行,config_item_type与之前的不一样,跟过去看看
- 371static struct configfs_group_operations group_children_group_ops = {
- 372 .make_group = group_children_make_group,
- 373};
- 374
- 375static struct config_item_type group_children_type = {
- 376 .ct_item_ops = &group_children_item_ops,
- 377 .ct_group_ops = &group_children_group_ops,
- 378 .ct_attrs = group_children_attrs,
- 379 .ct_owner = THIS_MODULE,
- 380};
375行,定义新的config_item_type,其根本区别在377行configfs_group_operations
371行,定义了configfs_group_operations,这里定义了make_group函数,在子系统下mkdir就会调用这个函数。
- 326static struct config_group *group_children_make_group(struct config_group *group, const char *name)
- 327{
- 328 struct simple_children *simple_children;
- 329
- 330 simple_children = kzalloc(sizeof(struct simple_children),
- 331 GFP_KERNEL);
- 332 if (!simple_children)
- 333 return ERR_PTR(-ENOMEM);
- 334
- 335 config_group_init_type_name(&simple_children->group, name,
- 336 &simple_children_type);
- 337
- 338 return &simple_children->group;
- 339}
这份代码非常眼熟,跟示例2中创建config_item太像了,只不过把所有对象由config_item改为config_group类型的。
336行,simple_children_type正是示例2中对应的config_item_type。
所以这里的创建步骤首先是创建一个为config_group的目录,再在这个目录下创建config_item的目录。
到这里为止,简单地了解了一下configfs的实现原理,在某些应用中不失为一种很好的手段。