littlefs的设计

Lobsters Hottest 工具

摘要

littlefs是一个专为微控制器设计的故障安全文件系统,具有掉电恢复能力、动态磨损均衡以及有限的RAM/ROM。它提供类似POSIX的API,并用C语言编写,以实现较小的内存占用。

<p><a href="https://lobste.rs/s/mhymex/design_littlefs">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/06/18 22:07

littlefs-project/littlefs

来源:https://github.com/littlefs-project/littlefs

littlefs

一款专为微控制器设计的小型故障安全文件系统。

| | | .---._____ .-----. | | --|o |---| littlefs | --| |---| | '-----' '----------' | | |

掉电恢复能力 - littlefs 设计用于处理随机断电故障。所有文件操作均具有强写时复制保证,若电源中断,文件系统将回退至最后一个已知的良好状态。

动态磨损均衡 - littlefs 专为闪存设计,在动态块上提供磨损均衡。此外,littlefs 能够检测坏块并绕过它们。

有限 RAM/ROM - littlefs 设计用于少量内存。RAM 使用严格受限,意味着内存消耗不会随文件系统增长而变化。文件系统不包含无界递归,动态内存限制为可配置的缓冲器,这些缓冲器可以静态提供。

示例

以下是一个简单示例,每次 main 运行时更新名为 boot_count 的文件。程序可以随时中断,而不会丢失已启动次数的记录,也不会损坏文件系统:

`` c #include “lfs.h”

// 文件系统使用的变量 lfs_t lfs; lfs_file_t file;

// 文件系统的配置由此结构体提供 const struct lfs_config cfg = { // 块设备操作 .read = user_provided_block_device_read, .prog = user_provided_block_device_prog, .erase = user_provided_block_device_erase, .sync = user_provided_block_device_sync,

// 块设备配置
.read_size = 16,
.prog_size = 16,
.block_size = 4096,
.block_count = 128,
.cache_size = 16,
.lookahead_size = 16,
.block_cycles = 500,

};

// 入口点 int main(void) { // 挂载文件系统 int err = lfs_mount(&lfs, &cfg);

// 如果无法挂载文件系统则重新格式化
// 这仅应在首次启动时发生
if (err) {
    lfs_format(&lfs, &cfg);
    lfs_mount(&lfs, &cfg);
}

// 读取当前计数值
uint32_t boot_count = 0;
lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));

// 更新启动计数
boot_count += 1;
lfs_file_rewind(&lfs, &file);
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));

// 注意:存储更新仅在文件成功关闭后生效
lfs_file_close(&lfs, &file);

// 释放使用的所有资源
lfs_unmount(&lfs);

// 打印启动计数
printf("boot_count: %d\n", boot_count);

} ``

用法

详细文档(至少是目前可用的细节)可以在 lfs.h 的注释中找到。

littlefs 接收一个定义文件系统操作方式的配置结构体。配置结构体向文件系统提供块设备操作和尺寸、可调节参数(用于权衡内存使用和性能),以及可选的静态缓冲区(若用户希望避免动态内存)。

littlefs 的状态存储在 lfs_t 类型中,该类型由用户分配,从而可以同时使用多个文件系统。使用 lfs_t 和配置结构体,用户可以格式化块设备或挂载文件系统。

挂载后,littlefs 提供了一整套类 POSIX 的文件和目录函数,不同之处在于文件系统结构的分配必须由用户提供。

所有 POSIX 操作(如删除和重命名)都是原子性的,即使在断电情况下也是如此。此外,文件更新实际上不会提交到文件系统,直到对文件调用 sync 或 close。

其他说明

Littlefs 使用 C 语言编写,并且特别地应该能够与任何符合 C99 标准的编译器编译。

所有 littlefs 调用都可能返回负错误码。错误可以是 lfs.henum lfs_error 中的某个错误,也可以是用户块设备操作返回的错误。

在配置结构体中,用户提供的 progerase 函数若实现已能检测损坏块,则可返回 LFS_ERR_CORRUPT 错误。然而,磨损均衡不依赖于这些函数的返回码,相反所有数据都会被读回并检查完整性。

如果您的存储缓存写入,请确保提供的 sync 函数将所有数据刷新到内存,并确保后续读取从内存获取数据,否则数据完整性无法保证。如果 write 函数不进行缓存,因此每次 readwrite 调用都直接访问内存,则 sync 函数可以简单地返回 0。

设计

从高层次来看,littlefs 是一个基于块的文件系统,使用小型日志存储元数据,使用更大的写时复制 (COW) 结构存储文件数据。

在 littlefs 中,这些成分构成了一种双层蛋糕结构:小型日志(称为元数据对)提供对存储设备上任意位置的元数据的快速更新,而 COW 结构则紧凑地存储文件数据且无磨损放大成本。

这两种数据结构均由块构建,这些块由公共块分配器提供。通过限制每个块在每次分配时可擦除的次数,分配器在整个文件系统上提供动态磨损均衡。

root .--------.--------. | A'| B'| | | | |-> | | | | | '--------'--------' .----' '--------------. A v B v .--------.--------. .--------.--------. | C'| D'| | | E'|new| | | | |-> | | | E'|-> | | | | | | | | | '--------'--------' '--------'--------' .-' '--. | '------------------. v v .-' v .--------. .--------. v .--------. | C | | D | .--------. write | new E | | | | | | E | ==> | | | | | | | | | | '--------' '--------' | | '--------' '--------' .-' | .-' '-. .-------------|------' v v v v .--------. .--------. .--------. | F | | G | | new F | | | | | | | | | | | | | '--------' '--------' '--------'

更多关于 littlefs 工作原理的细节可以在 DESIGN.mdSPEC.md 中找到。

  • DESIGN.md - 关于 littlefs 工作原理的全面深入探讨。建议阅读,因为其中的权衡取舍非常有趣。

  • SPEC.md - littlefs 的磁盘规范,包含所有具体细节。可能对工具开发有用。

测试

littlefs 附带一套测试套件,设计用于在 PC 上运行,使用 bd 目录中的仿真块设备。测试假定 Linux 环境,可以通过 make 启动:

bash make test

测试以 C 语言实现,位于 tests 目录的 .toml 文件中。在开发功能或修复错误时,经常需要运行单个测试用例或测试套件:

bash ./scripts/test.py -l runners/test_runner # 列出可用的测试套件 ./scripts/test.py -L runners/test_runner test_dirs # 列出可用的测试用例 ./scripts/test.py runners/test_runner test_dirs # 运行特定测试套件

如果测试中断言失败,test.py 将尝试打印失败信息:

bash tests/test_dirs.toml:1:failure: test_dirs_root:1g12gg2 (PROG_SIZE=16, ERASE_SIZE=512) failed tests/test_dirs.toml:5:assert: assert failed with 0, expected eq 42 lfs_mount(&lfs, cfg) => 42;

这包括测试 ID,可以传递给 test.py 以仅运行该特定测试排列:

bash ./scripts/test.py runners/test_runner test_dirs_root:1g12gg2 # 运行特定测试排列 ./scripts/test.py runners/test_runner test_dirs_root:1g12gg2 --gdb # 失败时进入 gdb

一些其他可能有用的标志:

bash ./scripts/test.py runners/test_runner -b -j # 并行运行测试 ./scripts/test.py runners/test_runner -v -O- # 将 stdout 重定向到 stdout ./scripts/test.py runners/test_runner -ddisk # 捕获生成的磁盘映像

查看 -h/--help 以获得所有可用标志的完整列表:

bash ./scripts/test.py --help

许可证

littlefs 使用 BSD-3-Clause 许可证提供。更多信息请参见 LICENSE.md。对本项目的贡献应以相同许可证接受。

个别文件包含以下标签,而非完整许可证文本。

SPDX-License-Identifier:    BSD-3-Clause

这使得基于 SPDX 许可证标识符(此处可用:http://spdx.org/licenses/)的许可证信息机器处理成为可能。

相关项目

  • littlefs-fuse - littlefs 的 FUSE 包装器。该项目允许您直接在 Linux 机器上挂载 littlefs。如果您有 SD 卡,可能对调试 littlefs 有用。

  • littlefs-js - littlefs 的 JavaScript 包装器。我不确定您为什么需要这个,但它对演示很有用。您可以在此处看到它的运行效果。

  • littlefs-python - littlefs 的 Python 包装器。该项目允许您在 PC 上创建文件系统映像。检查 littlefs 是否满足您的需求,创建后续下载到目标内存的映像,或检查目标内存二进制映像的内容。

  • littlefs-toy - 用于创建和处理 littlefs 映像的命令行工具。语法类似于 tar 命令,易于使用。支持处理嵌入在其他文件(固件映像等)中的 littlefs 映像。

  • littlefs2-rust - littlefs 的 Rust 包装器。该项目允许您使用 Rust 友好的 API 使用 littlefs,从而受益于 Rust 的内存安全性及其他保证。

  • nim-littlefs - littlefs 的 Nim 包装器和 API。包含基于 littlefs-fuse 的 FUSE 实现。

  • chamelon - 一个纯 OCaml 实现的 littlefs(大部分功能),设计用于 MirageOS 库操作系统项目。与参考实现可互操作,但有一些注意事项。

  • littlefs-disk-img-viewer - 一个内存效率高的 Web 应用程序,用于在 Web 浏览器中查看 littlefs 磁盘映像。

  • mklfs - 用于创建 littlefs 映像的命令行工具。用于 Lua RTOS 生态系统。

  • mklittlefs - 用于创建 littlefs 映像的命令行工具。用于 ESP8266 和 RP2040 生态系统。

  • pico-littlefs-usb - littlefs 的接口,通过 USB 模拟 FAT12 文件系统。允许在主机 PC 上挂载 littlefs 而无需额外驱动程序。

  • ramcrc32bd - 一个示例块设备,使用 littlefs 的 32 位 CRC 进行纠错。

  • ramrsbd - 一个示例块设备,使用 Reed-Solomon 码进行纠错。

  • Mbed OS - 入门 littlefs 的最简单方式是使用 Mbed,它已经为大多数嵌入式存储形式提供了块设备驱动程序。littlefs 在 Mbed OS 中作为 LittleFileSystem 类可用。

  • SPIFFS - 另一个优秀的 NOR 闪存嵌入式文件系统。作为一个具有完全静态磨损均衡的更传统的日志文件系统,SPIFFS 很可能在小型内存(如微控制器内部闪存)上胜过 littlefs。

  • Dhara - 一个专为小型微控制器设计的有趣的 NAND 闪存转换层。它提供静态磨损均衡和电源恢复能力,仅需在每个块和 RAM 中存储一个固定的 O(|address|) 指针结构。

  • ChaN’s FatFs - 臭名昭著的 FAT 文件系统在微控制器级别设备上的轻量级重新实现。由于 FAT 的局限性,它无法提供掉电恢复能力,但允许与 PC 轻松互操作。

相似文章

探索构建微型FUSE文件系统

Hacker News Top

本文将引导你使用Rust构建一个名为magicfs的最小FUSE文件系统,该系统使用metadata.json和blob文件作为后端存储,演示了名称查找、inode稳定性和内核缓存等核心文件系统概念。

单片软盘上的嵌入式Linux

Hacker News Top

FLOPPINUX 是一个完整的 Linux 发行版,可安装在一张 1.44MB 软盘上,支持 Intel 486DX 和 20MB RAM 等最低配置硬件。启动后进入终端,具有持久化存储和基本工具。