RK3568驱动指南|第八篇 设备树插件-第75章ConfigFS的核心数据结构

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第八期_设备树插件_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第75章ConfigFS的核心数据结构

在前面的章节中,我们对于ConfigFS 有了一个感性的认识,本章节将进一步深入,探讨ConfigFS的核心数据结构,这将为我们理解ConfigFS的内部工作原理提供基础。让我们一起深入学习ConfigFS的核心数据结构吧!

75.1 关键数据结构

接下来我们将要学习如何创建内核对象,然后生成对应的文件和目录。

在创建之前,我们先要了解下和ConfigFs文件系统相关的几个核心数据结构。

ConfigFS的核心数据结构主要包括以下几个部分:

  1. :是一个顶层的数据结构,用于表示整个ConfigFS子系统。它包含了根配置项组的指针,以及ConfigFS的其他属性和状态信息。
  2. :是一种特殊类型的配置项,表示一个配置项组。它可以包含一组相关的配置项,形成一个层次结构。config_group结构包含了父配置项的指针,以及指向子配置项的链表。
  3. :这是ConfigFS中最基本的数据结构,用于表示一个配置项。每个配置项都是一个内核对象,可以是设备、驱动程序、子系统等。结构包含了配置项的类型、名称、属性、状态等信息,以及指向父配置项和子配置项的指针。

这些数据结构之间的关系可以形成一个树形结构,其中configfs_subsystem是根节点,config_group表示配置项组,config_item表示单个配置项。子配置项通过链表连接在一起,形成父子关系。如下表(图 75-1)所示:

75.2 子系统、容器和config_item

本小节我们来了解下子系统,容器,config_item的结构体。

configfs_subsystem结构体,如下所示:

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

configfs_subsystem结构体中包含config_group结构体,config_group结构体如下所示:

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结构体中包含config_item结构体,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;
};

接下来我们来分析设备树插件驱动代码,如下(图 75-2)所示:

图 75-2

这段代码定义了一个名为dtbocfg_root_subsysconfigfs_subsystem结构体实例,表示ConfigFS中的一个子系统。

首先,dtbocfg_root_subsys.su_group是一个config_group结构体,它表示子系统的根配置项组。在这里,该结构体的.cg_item字段表示根配置项组的基本配置项。

  1. = "device-tree":配置项的名称设置为"device-tree",表示该配置项的名称为"device-tree"。
  2. = &dtbocfg_root_type:配置项的类型设置为dtbocfg_root_type,这是一个自定义的配置项类型。

接下来,.su_mutex字段是一个互斥锁,用于保护子系统的操作。在这里,使用了__MUTEX_INITIALIZER宏来初始化互斥锁。

通过这段代码,创建了一个名为"device-tree"的子系统,它的根配置项组为空。可以在该子系统下添加更多的配置项和配置项组,用于动态配置和管理设备树相关的内核对象。Linux系统下创建了device-tree这个子系统,如下图(图 75-3)所示:

图 75-3

接下来继续分析设备树插件驱动代码中注册配置项组的部分,如下图(图 75-4)所示:

图 75-4

这段代码是一个初始化函数dtbocfg_module_init(),用于初始化和注册ConfigFS子系统和配置项组。首先,通过config_group_init()函数初始化了dtbocfg_root_subsys.su_group,即子系统的根配置项组。接下来,使用config_group_init_type_name()函数初始化了dtbocfg_overlay_group,表示名为"overlays"的配置项组,并指定了配置项组的类型为dtbocfg_overlays_type,这是一个自定义的配置项类型。然后,调用configfs_register_subsystem()函数注册了dtbocfg_root_subsys子系统。如果注册失败,将打印错误信息,并跳转到register_subsystem_failed标签处进行错误处理。接着,调用configfs_register_group()函数注册了dtbocfg_overlay_group配置项组,并将其添加到dtbocfg_root_subsys.su_group下。如果注册失败,同样会打印错误信息,并跳转到register_group_failed标签处进行错误处理。最后,如果所有的注册过程都成功,将打印"OK"消息,并返回0,表示初始化成功。如果在注册配置项组失败时,会先调用configfs_unregister_subsystem()函数注销之前注册的子系统,然后返回注册失败的错误码retval。

这段代码的作用是初始化和注册一个名为"device-tree"的ConfigFS子系统,并在其下创建一个名为"overlays"的配置项组。Linux系统下,在device-tree子系统下创建了overlays容器,如下图(图 75-5)所示:

图 75-5

75.3 属性和方法

我们要在容器下放目录或属性文件,所以我们看一下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结构体,config_item_type结构体如下所示:

struct config_item_type {
	struct module				*ct_owner;
	struct configfs_item_operations		*ct_item_ops;  //item(目录)的操作方法
	struct configfs_group_operations	*ct_group_ops;  //group(容器)的操作方法
	struct configfs_attribute		**ct_attrs;     //属性文件的操作方法
	struct configfs_bin_attribute		**ct_bin_attrs; //bin属性文件的操作方法
};
  1. 结构体中包含了struct configfs_item_operations结构体,如下所示:
struct configfs_item_operations {
//删除item方法,在group下面使用rmdir命令会调用这个方法
	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);
};
  1. 结构体中包含了struct configfs_group_operations结构体,如下所示:
struct configfs_group_operations {
	//创建item的方法,在group下面使用mkdir命令会调用这个方法
struct config_item *(*make_item)(struct config_group *group, const char *name); 
	//创建group的方法
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);
};
  1. 结构体中包含了struct 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);  };

75.4 总结

在上面几个小节中,对ConfigFS的核心数据结构做出了详细的解释,本小节我们来总结一下。这些核心数据结构相互关联,通过在ConfigFS层级结构进行组织和管理,使得设备的配置和管理更加灵活和可定制。如下图(图 75-6)所示:

图 75-6

理解ConfigFS的核心数据结构对于深入使用和定制ConfigFS非常重要,可以帮助开发者更好地进行设备的配置和管理,提高系统的灵活性和可扩展性。如果大家还有不理解的地方,建议反复观看视频学习。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值