一、什么是configfs
是一种基于ram的文件系统

configfs is a ram-based filesystem that provides the converse of sysfs's functionality.  Where sysfs is a filesystem-based view of kernel objects, configfs is a filesystem-based manager of kernel objects, or config_items.

二、configfs有什么用处
在用户空间配置内核对象
三、configfs VS ioctl
configfs可直接察看,通过用户态目录文件访问接口,适用于内核对象有众多复杂的配置。
四、configs VS sysfs
configfs可以在用户态创建和删除内核对象。

With sysfs, an object is created in kernel (for example, when a device is discovered) and it is registered with sysfs.  Its attributes then appear in sysfs, allowing userspace to read the attributes via readdir(3)/read(2).  It may allow some attributes to be modified via write(2).  The important point is that the object is created and destroyed in kernel, the kernel controls the lifecycle of the sysfs representation, and sysfs is merely a window on all this.
A configfs config_item is created via an explicit userspace operation: mkdir(2).  It is destroyed via rmdir(2).  The attributes appear at mkdir(2) time, and can be read or modified via read(2) and write(2). As with sysfs, readdir(3) queries the list of items and/or attributes. symlink(2) can be used to group items together.  Unlike sysfs, the lifetime of the representation is completely driven by userspace.  The kernel modules backing the items must respond to this.
Both sysfs and configfs can and should exist together on the same system.  One is not a replacement for the other.

五、什么时候用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是目录下面的属性。
八、如何运用configfs

configfs can be compiled as a module or into the kernel.  You can access it by doing
mount -t configfs none /config

The configfs tree will be empty unless client modules are also loaded. These are modules that register their item types with configfs as subsystems.  Once a client subsystem is loaded, it will appear as a subdirectory (or more than one) under /config.  Like sysfs, the configfs tree is always there, whether mounted on /config or not.

An item is created via mkdir(2).  The item's attributes will also appear at this time.  readdir(3) can determine what the attributes are, read(2) can query their default values, and write(2) can store new values.  Don't mix more than one attribute in one attribute file.

There are two types of configfs attributes:

* Normal attributes, which similar to sysfs attributes, are small ASCII text files, with a maximum size of one page (PAGE_SIZE, 4096 on i386).  Preferably only one value per file should be used, and the same caveats from sysfs apply. Configfs expects write(2) to store the entire buffer at once.  When writing to normal configfs attributes, userspace processes should first read the entire file, modify the portions they wish to change, and then write the entire buffer back.

* Binary attributes, which are somewhat similar to sysfs binary attributes, but with a few slight changes to semantics.  The PAGE_SIZE limitation does not apply, but the whole binary item must fit in single kernel vmalloc'ed buffer. The write(2) calls from user space are buffered, and the attributes' write_bin_attribute method will be invoked on the final close, therefore it is imperative for user-space to check the return code of close(2) in order to verify that the operation finished successfully. To avoid a malicious user OOMing the kernel, there's a per-binary attribute maximum buffer value.

When an item needs to be destroyed, remove it with rmdir(2).  An item cannot be destroyed if any other item has a link to it (via symlink(2)).  Links can be removed via unlink(2).

九、Coding With configfs

Every object in configfs is a config_item.  A config_item reflects an object in the subsystem.  It has attributes that match values on that object.  configfs handles the filesystem representation of that object and its attributes, allowing the subsystem to ignore all but the basic show/store interaction.
Items are created and destroyed inside a config_group.  A group is a collection of items that share the same attributes and operations. Items are created by mkdir(2) and removed by rmdir(2), but configfs handles that.  The group has a set of operations to perform these tasks
A subsystem is the top level of a client module.  During initialization, the client module registers the subsystem with configfs, the subsystem appears as a directory at the top of the configfs filesystem.  A subsystem is also a config_group, and can do everything a config_group can.

十、代码示例(来自内核目录Documentation\filesystems\configfs)
介绍代码之前,先过一下基本的数据结构:

struct configfs_subsystem {struct config_group   su_group;struct mutex       su_mutex;
};

configfs子系统,config_group是抽象容器,之所以叫容器,是因为容器中可以包括config_item,还可以递归包含config_group。struct mutex是用于子系统访问控制的。
struct config_group {struct config_item       cg_item;struct list_head        cg_children;struct configfs_subsystem   *cg_subsys;struct list_head     default_groups;struct list_head     group_entry;
};

config_group作为幕后主使,是不轻易出现在台前的。所以有了94行的struct config_item来表现为一个目录。

struct config_item {char         *ci_name;char           ci_namebuf[CONFIGFS_ITEM_NAME_LEN];struct kref      ci_kref;struct list_head    ci_entry;struct config_item *ci_parent;struct config_group  *ci_group;struct config_item_type   *ci_type;struct dentry      *ci_dentry;
}; 

config_item             行为目录名称。
config_item_type 行为目录下属性和属性操作,属性表现为目录下的文本文件。
struct config_item_type {struct module             *ct_owner;struct configfs_item_operations       *ct_item_ops;struct configfs_group_operations   *ct_group_ops;struct configfs_attribute     **ct_attrs;struct configfs_bin_attribute        **ct_bin_attrs;
};

configfs_item_operations行为属性操作方法,操作对象是configfs_attribute属性。

configfs_group_operations行为目录操作方法,可以在当前目录下创建item或group。
configfs_attribute行为当前目录属性数组。
struct configfs_attribute {const char       *ca_name;struct module      *ca_owner;umode_t           ca_mode;ssize_t (*show)(struct config_item *, char *);ssize_t (*store)(struct config_item *, const char *, size_t);
};

属性非常简单,有属性名称、所属模块和访问权限。
示例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

linux之configfs简介和编程入门相关推荐

  1. linux c语言 ppt,linux操作系统下c语言编程入门.ppt

    linux操作系统下c语言编程入门.ppt Linux操作系统下C语言编程入门 CNT Linux操作系统简介基础知识进程介绍文件操作时间概念消息管理线程操作网络编程Linux下C开发工具介绍 一 L ...

  2. linux Shell(脚本)编程入门实例讲解详解

    linux Shell(脚本)编程入门实例讲解详解 为什么要进行shell编程 在Linux系统中,虽然有各种各样的图形化接口工具,但是sell仍然是一个非常灵活的工具.Shell不仅仅是命令的收集, ...

  3. linux操作系统下 c语言编程入门

    linux操作系统下 c语言编程入门 (一)目录介绍 1)Linux程序设计入门--基础知识 2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门 ...

  4. linux操作系统下c语言编程入门

    linux操作系统下c语言编程入门  整理编写:007xiong  原文:Hoyt等 (一)目录介绍 1)Linux程序设计入门--基础知识  2)Linux程序设计入门--进程介绍  3)Linux ...

  5. 【转贴】linux操作系统下c语言编程入门

    [转贴]linux操作系统下c语言编程入门 发信人: Lerry (驴是的念来过倒·杏红等头墙上爬), 信区: Linux 标 题: linux操作系统下c语言编程入门 发信站: 哈工大紫丁香 (Fr ...

  6. [转] linux操作系统下c语言编程入门

    (一)目录介绍 1)Linux程序设计入门--基础知识  2)Linux程序设计入门--进程介绍  3)Linux程序设计入门--文件操作  4)Linux程序设计入门--时间概念  5)Linux程 ...

  7. linux 操作系统下c语言编程入门

    2)Linux程序设计入门--进程介绍  3)Linux程序设计入门--文件操作  4)Linux程序设计入门--时间概念  5)Linux程序设计入门--信号处理  6)Linux程序设计入门--消 ...

  8. Linux下的shell语言编程入门

    通常情况下,我们从命令行输入命令每输入一次就能够得到系统的一次响应.一旦需要我们一个接着一个的输入命令而最后才得到结果的时候,这样的做法显然就没有效率.要达到这样的目的,通常我们利用shell程序或者 ...

  9. Linux进阶之路———Shell 编程入门

    引言 通过 Shell 编程的学习,铺平架构师道路上的一块大砖. Shell 在Linux 系统中的定位如下所示: 一.第一个 Shell 脚本 我们通过一个简单的 Shell 脚本来感受一下. 在 ...

最新文章

  1. eclipse+adt下开发android微信红包自动抢(AccessibilityService类)
  2. 洛谷精选 - 字符串合集
  3. 给你这张图,你能搜索到来历吗
  4. 五大成功企业家的成功创业箴言
  5. 让效率“爆表”的49个数据可视化工具
  6. 非现场执法管理计算机(工业级),浅析非现场执法中存在问题的方法及对策
  7. Python中的unittest模块(入门学习款)
  8. yacc c语言语法分析,编译原理实践--语法分析程序的自动生成工具YACC.PPT
  9. 基于SSD目标检测模型的人脸口罩识别
  10. 美团外卖uml流程图_以美团外卖为例,区别业务流程图和页面流程图 | 人人都是产品经理...
  11. Oracle的sql基本语法总结(3)-- Oracle synonym 同义词的创建、查看、删除、作用
  12. 高等数学(第七版)同济大学 总习题七 (前4题)个人解答
  13. 做京东运营2年的感悟(转自派代网 乔先生)
  14. 第5章-LC3, latency and QoS
  15. 去重数组中相同的字符串
  16. CleanMyMac序列号密钥如何清理苹果电脑内存?
  17. 华三交换机irf堆叠以及BFD检测配置
  18. 卧槽!百度网盘宣布 VIP 开放免费领取!亲测有效!!
  19. 手游逆向专题<英雄联盟手游>: Unity内还原亚索渲染效果
  20. 金山办公 服务端开发岗位 面经 2019.11.11(秋招)

热门文章

  1. 新上线的网站需要做什么(SEO优化类)
  2. 【项目总结】第三方OA对接、项目从零入手
  3. 微信小程序开发笔记--03
  4. html语言中的表单元素,HTML5中的表单元素有哪些
  5. VMware Linux 下安装 Oracle 11gR2 RAC
  6. 华为手机荣耀,连接电脑,照片不显示
  7. 【AI训练新手记:如何通过ChatGPT生成令人惊艳的文案!】
  8. 西门子S7-1200数据处理指令应用|阶段性题目
  9. 什么是钩子(Hook)
  10. 成功上市、新品抱抱果销量过千万,百草味做对了什么?