LVFS POSIX 文件操作示例
源码位置: samples/subsys/fs/posix/fs 查看源码
功能说明
演示通过 LVFS (LiSa Virtual File System) 层使用标准 POSIX API 进行文件操作,包括文件描述符操作和标准 I/O 流操作两种方式。
LVFS 提供 POSIX 兼容接口,应用层通过标准的 open(), read(), write(), fopen(), fread(), fwrite() 等 API 操作文件,LVFS 内部转发调用到 LSFS 处理。本示例在 SD 卡上演示两种 POSIX 接口的使用。
新特性
标准 POSIX 兼容:使用标准 C 库文件操作 API,便于移植现有应用
双接口支持:支持文件描述符接口(
open/read/write)和流接口(fopen/fread/fwrite)透明调用:应用层无需关心底层实现,LVFS 自动转发到 LSFS
完整功能集:支持文件定位(
lseek/fseek)、截断(ftruncate)、同步(fsync/fflush)
硬件连接
SDMMC0 接口:连接 SD 卡模块
具体引脚定义参见板级配置文件
使用场景
适用于需要标准 POSIX 兼容的应用场景,特别是从其他操作系统(如 Linux)移植应用程序时,可以直接使用熟悉的文件操作 API,降低移植成本。
示例步骤
初始化 SD 卡和磁盘子系统
初始化 LVFS 和 LSFS 框架
挂载 SD 卡文件系统(挂载失败时自动格式化)
测试文件描述符接口:
使用
open()创建文件使用
write()写入数据使用
lseek()定位文件指针使用
read()读取数据并验证使用
fsync()同步到磁盘使用
ftruncate()截断文件使用
close()关闭文件
测试标准 I/O 流接口(如果启用
CONFIG_LVFS_POSIX_API_ALIAS):使用
fopen()创建文件流使用
fwrite()写入数据使用
fseek()定位文件指针使用
fread()读取数据并验证使用
fflush()刷新缓冲区使用
fclose()关闭文件流
卸载文件系统
编译
重要提示:在编译前,请先确认您使用的开发板型号。SDK 目前支持以下开发板:
arcs_evb - ARCS EVB 评估板
arcs_mini - ARCS Mini 开发板
根据您的开发板型号,选择对应的编译命令:
在示例目录下执行编译:
# 使用 arcs_evb 开发板
./build.sh -C -DBOARD=arcs_evb
# 或使用 arcs_mini 开发板
./build.sh -C -DBOARD=arcs_mini
Note
如果在 SDK 根目录执行,需要指定示例路径:
# 使用 arcs_evb 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_evb
# 或使用 arcs_mini 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_mini
Note
确保已安装对应的工具链。
烧录
编译完成后,使用 SDK tools 目录下的 cskburn 工具烧录固件:
./tools/burn/cskburn -s /dev/ttyUSB0 -b 3000000 0x0 build/arcs.bin -C arcs
Note
烧录参数说明:
-s /dev/ttyUSB0:串口设备路径,需要根据实际情况修改 - Linux 系统:通常是/dev/ttyUSB0或/dev/ttyACM0- 可通过ls /dev/tty*命令查看可用串口设备 - 不同开发板或 USB 转串口芯片可能使用不同的设备名-b 3000000:烧录波特率(3Mbps)0x0:烧录起始地址build/arcs.bin:编译生成的固件路径-C arcs:芯片类型
注意事项:
确保开发板已正确连接到电脑
如果无法识别串口设备,请检查 USB 连接线是否正常,或尝试其他 USB 端口
预期输出
终端输出:
=== LVFS POSIX Sample ===
Mounted /SD: successfully
--- File Descriptor API Demo ---
write() wrote 13 bytes
read() read 13 bytes: Hello, POSIX!
fsync() completed
ftruncate() to 5 bytes
close() completed
--- Standard I/O Stream API Demo ---
fwrite() wrote 13 items
fflush() completed
fread() read 13 items: Hello, POSIX!
fclose() completed
Unmounted /SD:
核心 API
文件系统初始化 API
API |
说明 |
|---|---|
|
初始化 SD 卡设备 |
|
初始化磁盘子系统 |
|
初始化 LVFS 框架 |
|
初始化 LSFS 框架 |
|
挂载文件系统 |
|
卸载文件系统 |
POSIX 文件描述符接口
API |
说明 |
|---|---|
|
打开或创建文件(返回文件描述符) |
|
从文件描述符读取数据 |
|
向文件描述符写入数据 |
|
设置文件读写位置 |
|
同步文件数据到磁盘 |
|
截断文件到指定长度 |
|
关闭文件描述符 |
POSIX 标准 I/O 流接口(需启用 CONFIG_LVFS_POSIX_API_ALIAS)
API |
说明 |
|---|---|
|
打开文件流(返回 FILE 指针) |
|
从文件流读取数据 |
|
向文件流写入数据 |
|
设置文件流读写位置 |
|
刷新文件流缓冲区 |
|
关闭文件流 |
POSIX 接口说明
文件描述符接口
文件描述符接口是底层的 POSIX 文件操作方式,直接使用整数文件描述符:
特点:
返回整数文件描述符(
int fd)适合系统级编程
性能略高于流接口
使用
open(),read(),write(),close()
典型使用流程:
int fd = open("/SD:/test.txt", O_CREAT | O_RDWR, 0666);
write(fd, data, size);
lseek(fd, 0, SEEK_SET);
read(fd, buffer, size);
fsync(fd);
close(fd);
标准 I/O 流接口
标准 I/O 流接口是高层的 C 标准库接口,使用 FILE 指针:
特点:
返回 FILE 指针(
FILE *fp)符合 C 标准库规范
提供缓冲机制
适合应用级编程
使用
fopen(),fread(),fwrite(),fclose()
典型使用流程:
FILE *fp = fopen("/SD:/test.txt", "w+");
fwrite(data, 1, size, fp);
fseek(fp, 0, SEEK_SET);
fread(buffer, 1, size, fp);
fflush(fp);
fclose(fp);
关键代码
挂载点定义
#define SDMMC_DEVICE "SD:"
#define SDMMC_MOUNT_POINT "/SD:"
static struct lsfs_mount_t ram_lsfs_mnt = {
.type = LSFS_FATFS, // 使用 FatFS 文件系统
.mnt_point = "/SD:", // 挂载点路径
.fs_data = NULL, // 文件系统私有数据
};
初始化流程
// 1. 初始化 SD 卡设备
lisa_sdmmc_probe(lisa_device_get("sdmmc0"));
// 2. 初始化磁盘子系统
disk_init(NULL);
// 3. 初始化 LVFS 和 LSFS
lvfs_init(); // 必须先初始化 LVFS
lsfs_init();
// 4. 挂载文件系统
lsfs_mount(&ram_lsfs_mnt);
文件描述符操作示例
#include <fcntl.h>
#include <unistd.h>
// 打开文件
int fd = open("/SD:/sdmmc.txt", O_CREAT | O_RDWR, 0660);
// 写入数据
write(fd, "hello world!", 12);
// 定位到文件开头
lseek(fd, 0, SEEK_SET);
// 读取数据
char buffer[80];
ssize_t bytes = read(fd, buffer, sizeof(buffer));
// 同步到磁盘
fsync(fd);
// 截断文件
ftruncate(fd, 10);
// 关闭文件
close(fd);
标准 I/O 流操作示例
#include <stdio.h>
// 打开文件流
FILE *fp = fopen("/SD:/sdmmc.txt", "w+");
// 写入数据
fwrite("hello world!", 1, 12, fp);
// 刷新缓冲区
fflush(fp);
// 定位到文件开头
fseek(fp, 0, SEEK_SET);
// 读取数据
char buffer[80];
size_t bytes = fread(buffer, 1, sizeof(buffer), fp);
// 关闭文件流
fclose(fp);
配置说明
必需的配置项(prj.conf)
CONFIG_FILE_SYSTEM=y # 使能文件系统支持
CONFIG_FATFS_FILESYSTEM=y # 使能 FatFS 文件系统
CONFIG_DISK_DRIVER=y # 使能磁盘驱动
CONFIG_DISK_DRIVER_SDMMC=y # 使能 SD/MMC 磁盘驱动
CONFIG_LSFS=y # 使能 LSFS 抽象层
CONFIG_LSFS_FAT=y # 使能 LSFS 的 FatFS 支持
CONFIG_LSFS_REGISTER_VFS=y # 注册 LSFS 到 LVFS
CONFIG_LVFS=y # 使能 LVFS 虚拟文件系统
CONFIG_LVFS_POSIX_API=y # 使能 POSIX API 支持
CONFIG_LVFS_POSIX_API_ALIAS=y # 使能 POSIX API 别名(标准 I/O 流)
配置选项说明
CONFIG_LVFS_POSIX_API:使能 POSIX 文件描述符接口(open,read,write等)CONFIG_LVFS_POSIX_API_ALIAS:使能标准 I/O 流接口(fopen,fread,fwrite等)CONFIG_LSFS_REGISTER_VFS:自动注册 LSFS 到 LVFS,允许 POSIX API 访问 LSFS 文件系统
打开模式标志
open() 标志位
O_RDONLY // 只读模式
O_WRONLY // 只写模式
O_RDWR // 读写模式
O_CREAT // 文件不存在则创建
O_APPEND // 追加模式
O_TRUNC // 打开时清空文件
fopen() 模式字符串
"r" // 只读,文件必须存在
"w" // 只写,文件不存在则创建,存在则清空
"a" // 追加,文件不存在则创建
"r+" // 读写,文件必须存在
"w+" // 读写,文件不存在则创建,存在则清空
"a+" // 读写追加,文件不存在则创建
注意事项
初始化顺序:必须按照以下顺序初始化
先调用
lisa_sdmmc_probe()初始化 SD 卡设备再调用
disk_init()初始化磁盘子系统然后调用
lvfs_init()初始化 LVFS(必须在lsfs_init()之前)接着调用
lsfs_init()初始化 LSFS最后调用
lsfs_mount()挂载文件系统
错误处理:POSIX API 遵循标准错误处理机制
成功时返回非负值(文件描述符、字节数等)
失败时返回
-1并设置errno使用
errno获取具体错误码
文件描述符管理:
open()返回的文件描述符必须使用close()关闭不要混用文件描述符和 FILE 指针
流缓冲:
fwrite()写入的数据可能在缓冲区中使用
fflush()或fclose()确保数据写入磁盘文件描述符接口(
write())通常直接写入,但仍建议使用fsync()同步
路径格式:
文件路径必须包含挂载点(如
/SD:/test.txt)挂载点格式:
/设备名:(如/SD:,/RAM:)
配置依赖:
标准 I/O 流接口需要启用
CONFIG_LVFS_POSIX_API_ALIAS如果未启用,只能使用文件描述符接口
与 LSFS 接口的对比
特性 |
POSIX 接口(LVFS) |
LSFS 接口 |
|---|---|---|
接口风格 |
标准 POSIX API |
LSFS 专有 API |
移植性 |
符合 POSIX 标准,易于移植 |
ARCS SDK 特有 |
文件操作 |
|
|
文件对象 |
文件描述符( |
|
资源占用 |
略高(多一层 LVFS) |
更轻量级 |
适用场景 |
应用级开发、移植现有代码 |
资源受限的嵌入式系统 |
选择建议:
如果移植现有应用或需要标准兼容性,使用 POSIX 接口(本示例)
如果追求最小资源占用和直接控制,使用 LSFS 接口(参见
samples/subsys/fs/lsfs/)
扩展功能
LVFS 和 LSFS 支持更多高级功能,详见组件文档 modules/fs/README.md:
多存储介质:同时挂载 SD Card、Flash Disk、RAM Disk
目录操作:创建目录、删除文件、重命名(POSIX:
mkdir,unlink,rename)文件信息查询:
stat(),fstat()获取文件属性大文件支持:64位文件接口处理大于2GB的文件
工作目录管理:
chdir(),getcwd()