Linux configfs简介

文章介绍了Linux的configfs文件系统,它是一种基于内存的文件系统,允许用户在用户态创建和管理内核对象。特别提到usbgadgetconfigfs在USBgadget设备动态配置中的应用,以及configfs的数据结构和操作原理,如config_item、config_group和configfs_subsystem的使用方法。
摘要由CSDN通过智能技术生成
  1.        基本概念

         了解Linux configfs优先阅读kernel中configfs的文档,(https://www.kernel.org/doc/Documentation/filesystems/configfs/configfs.txt)。

        文档中介绍configfs是基于ram的文件系统,这一点与sysfs很像,但是与sysfs不同之处在于,configfs可以通过在用户态的操作创建和删除内核对象,而我们一般使用sysfs是已经有内核对象之后,再去创建sysfs文件节点。从使用上看都可以通过read write读取/修改文件属性,重点在于sysfs的内核对象是在内核创建、销毁的,sysfs是访问这些内核对象的窗口。但是configfs的内核对象的创建/销毁是由用户态的mkdir等操作完成,用户执行mkdir会在内核创建一个config_item对象,用户执行rmdir会销毁这个对象。

        这确实是一个很天才的想法,尤其适合动态修改配置以加载不同驱动的场景。例如,早期的USB只支持单一的gadget设备,使用场景较为简单,随后加入了composite framework,用来支持多个function的gadget设备,多个function的绑定在内核中完成,若需要修改,则需要修改内核,不灵活也不方便。Linux3.11版本引入了基于configfs的usb gadget configfs。usb gadget configfs重新实现了复合设备层,使用者可以在用户空间配置和组合内核的function,灵活的构成USB复合设备,极大了提高了工作效率。

2. 使用configfs

        configfs可以被编译成模块或者直接编译进内核,通过mount -t configfs none /sys/kernel/config/可以使用configfs

        configfs支持注册subsystem,官网介绍如下:

通过configfs_register_subsystem()configfs_subsystem给注册进去,注册完之后,相关的config_group就是可见的了,并且需要支持mkdir操作。usb gadget_subsys子系统的注册过程如下

static int __init gadget_cfs_init(void)
{
	int ret;

	config_group_init(&gadget_subsys.su_group);

	ret = configfs_register_subsystem(&gadget_subsys);
	return ret;
}
module_init(gadget_cfs_init);

3. configfs数据结构

        我们按照从顶往下的顺序来看,首先是subsystem,它是configfs的最顶层,比如:/sys/kernel/config/usb_gadget、/sys/kernel/config/iio

struct configfs_subsystem {
	struct config_group	su_group;    //config_subsystem是一类config_group
	struct mutex		su_mutex;
};

从configfs_subsystem数据结构中发现了config_group数据结构:

/**
 *	group - a group of config_items of a specific type, belonging
 *	to a specific subsystem.
 */
struct config_group {
	struct config_item		cg_item;        //config_group是一类config_item
	struct list_head		cg_children;
	struct configfs_subsystem 	*cg_subsys;
	struct list_head		default_groups;
	struct list_head		group_entry;
};

从config_group数据结构的注释中,我们知道config_group是一组config_items的组合,我们再看

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;
	const 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_attribute和configfs_bin_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);
};

configfs_attribute对应的文件含有的是可视化的字符串信息,读写文件时调用结构体里面的show/store函数

struct configfs_bin_attribute {
	struct configfs_attribute cb_attr;	/* std. attribute */
	void *cb_private;			/* for user       */
	size_t cb_max_size;			/* max core size  */
	ssize_t (*read)(struct config_item *, void *, size_t);
	ssize_t (*write)(struct config_item *, const void *, size_t);
};

configfs_bin_attribute对应的文件含有的是二进制信息,读写文件时read/write会被调用

文件所在的目录就是config_item,包括config_group和config_subsytem都是特殊的config_item。config_item下不再有别的目录,我们再看config_item支持的目录操作configfs_item_operations 

struct configfs_item_operations {
	void (*release)(struct config_item *);
	int (*allow_link)(struct config_item *src, struct config_item *target);
	void (*drop_link)(struct config_item *src, struct config_item *target);
};

包括对目录进行链接,可以使用symlink链接到其他目录。

config_group是一类特殊的config_item,它对应有一个目录,同时它支持另外一些目录操作:

struct configfs_group_operations {
	struct config_item *(*make_item)(struct config_group *group, const char *name);
	struct config_group *(*make_group)(struct config_group *group, const char *name);
	int (*commit_item)(struct config_item *item);
	void (*disconnect_notify)(struct config_group *group, struct config_item *item);
	void (*drop_item)(struct config_group *group, struct config_item *item);
};

make_item,支持在当前目录下创建item(make item)和group(make group),对应mkdir

  • 32
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bluetangos

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值