您的位置:首页 > 运维架构 > Linux

linux之configfs简介和编程入门

2013-09-29 10:39 423 查看
转载请注原出处:http://blog.csdn.net/liumangxiong
一、什么是configfs
是一种基于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

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
# 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

# cat test/storeme

0

# echo 1 > test/storeme

# cat test/storeme

1

示例3:创建group
之前我们讲过,config_group是可以嵌套的,那么现在就来看一下嵌套之后是什么样的:
# cd /sys/kernel/config/03-group-children/

# ls

description
# mkdir test
# mkdir test/test1
# mkdir test/test2
# mkdir test/test3
# tree

.

|-- 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的实现原理,在某些应用中不失为一种很好的手段。

转载请注原出处:http://blog.csdn.net/liumangxiong
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: