2、ConfigFS简介:ConfigFS文件系统原理、ConfigFS在USB Gadget中的作用、挂载ConfigFS到/sys/kernel/config

2.1 ConfigFS 文件系统原理

ConfigFS(Configuration File System)是一种基于内存的虚拟文件系统,它通过文件系统的目录和文件操作接口,向用户空间暴露内核对象的配置属性。与 sysfs 不同,ConfigFS 的设计目标是允许用户空间动态地创建、删除和配置内核对象,而不仅仅是读取或修改已有对象的属性。

ConfigFS 的核心原理可以概括为:目录即对象,文件即属性。用户通过 mkdir 创建目录来实例化一个内核对象,通过 rmdir 删除目录来销毁该对象,通过读写目录下的文件来配置对象的属性。

关键概念对比:ConfigFS vs sysfs
特性 ConfigFS sysfs
对象生命周期 用户空间通过 mkdir/rmdir 控制 内核驱动注册/注销时自动创建/销毁
主要用途 动态创建和配置内核对象 暴露内核对象拓扑和属性
操作模式 创建 → 配置 → 启用 读取/写入已有属性
典型挂载点 /sys/kernel/config /sys

ConfigFS 的目录结构遵循严格的层级关系。每个 ConfigFS 子系统(如 USB Gadget)会在 /sys/kernel/config 下创建一个顶级目录,用户在该目录下创建子目录来实例化具体的配置项。目录的命名和层级必须符合子系统的规范,否则操作会失败。

ConfigFS 文件系统原理:目录即对象,文件即属性 用户空间:mkdir / rmdir / echo / cat ConfigFS 虚拟文件系统(VFS 层) 内核对象实例(USB Gadget / UDC / 功能驱动) 目录 = 对象实例,文件 = 属性配置项 mkdir /sys/kernel/config/usb_gadget/g1 → 创建 Gadget 实例

2.2 ConfigFS 在 USB Gadget 中的作用

在 USB Gadget 子系统中,ConfigFS 扮演了配置总线的角色。它允许用户空间以文件系统操作的方式,完整地构建一个 USB 设备描述符层次结构,而无需编写内核代码或加载内核模块参数。

USB Gadget 的 ConfigFS 接口位于 /sys/kernel/config/usb_gadget/ 目录下。用户通过在该目录下创建目录来定义 Gadget 实例,然后在实例内部创建子目录来配置设备描述符、配置描述符、接口、端点以及功能驱动。

ConfigFS 在 USB Gadget 中的核心价值:
  • 动态性:无需重新编译内核或重启系统,即可创建和销毁 USB 设备。
  • 灵活性:支持多种功能组合(如 RNDIS + ACM + Mass Storage),通过目录结构自由组合。
  • 可脚本化:所有操作都可以通过 shell 脚本自动化,适合嵌入式系统初始化。
  • 标准化:遵循 Linux 内核统一的 ConfigFS 接口规范,与 UDC 驱动解耦。

典型的 USB Gadget ConfigFS 目录结构如下:

/sys/kernel/config/usb_gadget/
├── g1                              # Gadget 实例(由 mkdir 创建)
│   ├── UDC                         # 绑定到哪个 UDC 控制器(写入 UDC 名称)
│   ├── bcdUSB                      # USB 规范版本号
│   ├── bDeviceClass                # 设备类代码
│   ├── bDeviceSubClass             # 设备子类代码
│   ├── bDeviceProtocol             # 设备协议代码
│   ├── idVendor                    # 厂商 ID
│   ├── idProduct                   # 产品 ID
│   ├── bcdDevice                   # 设备版本号
│   ├── strings/                    # 字符串描述符
│   │   ├── 0x409/                  # 英语(美国)语言 ID
│   │   │   ├── manufacturer        # 厂商字符串
│   │   │   ├── product             # 产品字符串
│   │   │   └── serialnumber        # 序列号
│   ├── configs/                    # 配置描述符
│   │   ├── c.1/                    # 配置 1(由 mkdir c.1 创建)
│   │   │   ├── bmAttributes        # 配置属性
│   │   │   ├── MaxPower            # 最大功耗(mA)
│   │   │   ├── strings/0x409/
│   │   │   │   └── configuration   # 配置字符串
│   │   │   └── f1/                 # 功能实例(符号链接到功能驱动)
│   │   └── c.2/                    # 配置 2(可选)
│   └── functions/                  # 功能驱动目录
│       ├── rndis.usb0              # RNDIS 以太网功能
│       ├── acm.usb0                # ACM 串口功能
│       └── mass_storage.usb0       # 大容量存储功能
└── g2                              # 另一个 Gadget 实例(可选)

上图中,g1 是一个完整的 Gadget 实例。用户需要依次完成以下步骤:

  1. 创建 Gadget 实例目录(mkdir g1)。
  2. 写入设备描述符属性(idVendor、idProduct 等)。
  3. 创建字符串描述符目录和文件。
  4. 创建配置描述符目录(mkdir configs/c.1)。
  5. 创建功能驱动实例(mkdir functions/rndis.usb0)。
  6. 将功能驱动符号链接到配置描述符目录下(ln -s functions/rndis.usb0 configs/c.1/f1)。
  7. 将 Gadget 绑定到 UDC 控制器(echo <udc_name> > UDC)。
ConfigFS 在 USB Gadget 中的角色:配置总线 用户空间:shell 脚本 / 应用程序 ConfigFS 接口(/sys/kernel/config/usb_gadget/) USB Gadget 核心层(Composite Framework) 解析 ConfigFS 目录结构,构建 USB 描述符 UDC 驱动层(DWC2 / DWC3 / Chipidea ...) USB 硬件控制器

2.3 挂载 ConfigFS 到 /sys/kernel/config

在使用 ConfigFS 创建 USB Gadget 设备之前,必须确保 ConfigFS 文件系统已经挂载到 /sys/kernel/config 目录。如果该目录不存在或未挂载,所有 ConfigFS 操作都会失败。

常见故障点:许多嵌入式系统在默认启动时不会自动挂载 ConfigFS。如果执行 ls /sys/kernel/config 发现目录为空或不存在,需要手动挂载。

挂载步骤:

  1. 检查是否已挂载:
    mount | grep configfs
    如果输出为空,说明 ConfigFS 未挂载。
  2. 创建挂载点(如果不存在):
    mkdir -p /sys/kernel/config
  3. 挂载 ConfigFS:
    mount -t configfs none /sys/kernel/config
  4. 验证挂载结果:
    ls /sys/kernel/config/
    # 应看到 usb_gadget 等子系统目录

自动挂载配置:

为了确保系统重启后 ConfigFS 自动挂载,建议在 /etc/fstab 中添加以下条目:

none  /sys/kernel/config  configfs  defaults  0  0

或者,在系统初始化脚本(如 /etc/rc.local 或 systemd 服务)中添加挂载命令。

挂载状态检查清单:
检查项 命令 预期结果
挂载点是否存在 ls -d /sys/kernel/config 目录存在
文件系统类型 mount | grep configfs 显示 configfs on /sys/kernel/config type configfs
子系统目录 ls /sys/kernel/config/ 至少包含 usb_gadget(如果内核支持)
内核配置 cat /boot/config-$(uname -r) | grep CONFIG_CONFIGFS_FS CONFIG_CONFIGFS_FS=y 或 =m
ConfigFS 挂载流程 步骤 1 检查挂载状态 步骤 2 创建挂载点 步骤 3 执行挂载命令 步骤 4 验证结果 命令示例 mount -t configfs none /sys/kernel/config 建议:在 /etc/fstab 中添加自动挂载条目 none /sys/kernel/config configfs defaults 0 0

内核配置要求:

ConfigFS 和 USB Gadget ConfigFS 支持需要在内核编译时启用以下选项:

CONFIG_CONFIGFS_FS=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGETFS=y          # 可选,用于 GadgetFS 兼容
CONFIG_USB_CONFIGFS=y          # USB Gadget ConfigFS 接口
CONFIG_USB_CONFIGFS_SERIAL=y   # 串口功能
CONFIG_USB_CONFIGFS_ACM=y      # ACM 调制解调器功能
CONFIG_USB_CONFIGFS_ECM=y      # 以太网控制模型
CONFIG_USB_CONFIGFS_RNDIS=y    # RNDIS 功能
CONFIG_USB_CONFIGFS_MASS_STORAGE=y  # 大容量存储功能

如果内核未启用 CONFIG_USB_CONFIGFS,即使 ConfigFS 已挂载,/sys/kernel/config/ 下也不会出现 usb_gadget 目录。