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

linux之configfs简介和编程入门

2018-04-08 11:56 465 查看
一、什么是configfs是一种基于ram的文件系统二、configfs有什么用处在用户空间配置内核对象三、configfs VS ioctlconfigfs可直接察看,通过用户态目录文件访问接口,适用于内核对象有众多复杂的配置。四、configs VS sysfsconfigfs可以在用户态创建和删除内核对象。五、什么时候用configfs当内核需要很多参数需要配置时;当需要动态创建内核对象并且内核对象需要修改配置时;不想写用户态程序和ioctl时,写shell脚本就可以直接配置configfs。六、怎么知道系统上是否已经安装了configfs,安装在哪个目录执行如下命令,可以看到安装目录为/sys/kernel/configcat /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)介绍代码之前,先过一下基本的数据结构:[cpp] view plain copy 240struct configfs_subsystem {  
241     struct config_group     su_group;  
242     struct mutex          su_mutex;  
243};  
configfs子系统,config_group是抽象容器,之所以叫容器,是因为容器中可以包括config_item,还可以递归包含config_group。struct mutex是用于子系统访问控制的。[cpp] view plain copy 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来表现为一个目录。[cpp] view plain copy 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行为目录下属性和属性操作,属性表现为目录下的文本文件。[cpp] view plain copy 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行为当前目录属性数组。[cpp] view plain copy 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
[cpp] view plain copy 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可以放子系统下,为什么其他两个属性不行呢?有谁知道的告知一下。子系统定义如下:[cpp] view plain copy 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行,定义属性和操作。接着看属性和操作的定义:[cpp] view plain copy 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/下看到创建了子系统了。[cpp] view plain copy 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_subsystem2、创建子系统下config_item_type,对应位置configfs_subsystem->config_group->config_item->config_item_type3、创建config_item_type对应的属性数组和操作,操作主要是show_attribute和store_attribute4、注册子系统configfs_register_subsystem
示例2:创建一个configfs目录,用户空间可创建目录(新的内核对象)首先是定义configfs子系统,[cpp] view plain copy 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,[cpp] view plain copy 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[cpp] view plain copy 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类型?[cpp] view plain copy 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的区别了吗?首先看子系统定义[cpp] view plain copy 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与之前的不一样,跟过去看看[cpp] view plain copy 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_operations371行,定义了configfs_group_operations,这里定义了make_group函数,在子系统下mkdir就会调用这个函数。[cpp] view plain copy 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: