littlefs-project/littlefs
GitHub: littlefs-project/littlefs
专为微控制器设计的轻量级容错文件系统,具备断电恢复和闪存磨损均衡能力。
Stars: 6454 | Forks: 968
## littlefs
一个专为微控制器设计的小型容错文件系统。
```
| | | .---._____
.-----. | |
--|o |---| littlefs |
--| |---| |
'-----' '----------'
| | |
```
**断电恢复能力** - littlefs 旨在处理随机的电源故障。所有文件操作都具有强有力的写时复制保障,如果发生断电,文件系统将回退到上一个已知的良好状态。
**动态磨损均衡** - littlefs 专为闪存设计,并在动态块上提供磨损均衡。此外,littlefs 可以检测坏块并对其进行处理。
**有限的 RAM/ROM** - littlefs 设计用于在少量内存下工作。RAM 使用量受到严格限制,这意味着 RAM 消耗不会随着文件系统的增长而改变。文件系统不包含无界递归,动态内存仅限于可静态提供的可配置缓冲区。
## 示例
这是一个简单的示例,每次运行 main 时都会更新一个名为 `boot_count` 的文件。该程序可以在任何时候被中断,而不会丢失其启动次数的记录,也不会损坏文件系统:
```
#include "lfs.h"
// variables used by the filesystem
lfs_t lfs;
lfs_file_t file;
// configuration of the filesystem is provided by this struct
const struct lfs_config cfg = {
// block device operations
.read = user_provided_block_device_read,
.prog = user_provided_block_device_prog,
.erase = user_provided_block_device_erase,
.sync = user_provided_block_device_sync,
// block device configuration
.read_size = 16,
.prog_size = 16,
.block_size = 4096,
.block_count = 128,
.cache_size = 16,
.lookahead_size = 16,
.block_cycles = 500,
};
// entry point
int main(void) {
// mount the filesystem
int err = lfs_mount(&lfs, &cfg);
// reformat if we can't mount the filesystem
// this should only happen on the first boot
if (err) {
lfs_format(&lfs, &cfg);
lfs_mount(&lfs, &cfg);
}
// read current count
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));
// update boot count
boot_count += 1;
lfs_file_rewind(&lfs, &file);
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
// remember the storage is not updated until the file is closed successfully
lfs_file_close(&lfs, &file);
// release any resources we were using
lfs_unmount(&lfs);
// print the boot count
printf("boot_count: %d\n", boot_count);
}
```
## 用法
详细的文档(或者至少是目前可用的详细程度)可以在 [lfs.h](lfs.h) 的注释中找到。
littlefs 接受一个定义文件系统如何运行的配置结构。该配置结构体为文件系统提供块设备操作和维度、用于在内存使用和性能之间进行权衡的可调参数,以及可选的静态缓冲区(如果用户希望避免动态内存分配)。
littlefs 的状态存储在 `lfs_t` 类型中,该类型由用户自行分配,允许同时使用多个文件系统。使用 `lfs_t` 和配置结构体,用户可以格式化块设备或挂载文件系统。
一旦挂载,littlefs 提供一套完整的类 POSIX 文件和目录函数,其不同之处在于文件系统结构的分配必须由用户提供。
所有 POSIX 操作(例如 remove 和 rename)都是原子的,即使在发生断电时也是如此。此外,在调用 sync 或 close 之前,文件更新实际上并未提交到文件系统。
## 其他说明
Littlefs 使用 C 语言编写,特别是应该可以通过任何符合 `C99` 标准的编译器进行编译。
所有 littlefs 调用都有可能返回负错误代码。这些错误可以是 [lfs.h](lfs.h) 中 `enum lfs_error` 中的错误之一,或者是用户块设备操作返回的错误。
在配置结构体中,如果实现已经可以检测到损坏的块,用户提供的 `prog` 和 `erase` 函数可能会返回 `LFS_ERR_CORRUPT` 错误。但是,磨损均衡不依赖于这些函数的返回代码,而是会回读所有数据并检查其完整性。
如果您的存储设备缓存写入,请确保提供的 `sync` 函数将所有数据刷新到内存,并确保下一次读取是从内存中获取数据,否则无法保证数据完整性。如果 `write` 函数不执行缓存,因此每次 `read` 或 `write` 调用都直接访问内存,则 `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.md](DESIGN.md) 和 [SPEC.md](SPEC.md) 中找到。
- [DESIGN.md](DESIGN.md) - 深入探讨 littlefs 工作原理的完整详细文档。
我建议阅读它,因为其中的权衡设计非常有趣。
- [SPEC.md](SPEC.md) - littlefs 的磁盘规范,包含所有具体的细节。可能对工具开发有用。
## 测试
littlefs 附带一个测试套件,旨在使用 `bd` 目录中的 [模拟块设备](bd/lfs_testbd.h) 在 PC 上运行。
测试假设使用 Linux 环境,可以通过 make 启动:
```
make test
```
测试是用 C 语言在 `tests` 目录中的 .toml 文件中实现的。
在开发功能或修复错误时,运行单个测试用例或测试套件通常很有用:
```
./scripts/test.py -l runners/test_runner # list available test suites
./scripts/test.py -L runners/test_runner test_dirs # list available test cases
./scripts/test.py runners/test_runner test_dirs # run a specific test suite
```
如果测试中的断言失败,test.py 将尝试打印有关失败的信息:
```
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 以仅运行该特定的测试排列:
```
./scripts/test.py runners/test_runner test_dirs_root:1g12gg2 # run a specific test permutation
./scripts/test.py runners/test_runner test_dirs_root:1g12gg2 --gdb # drop into gdb on failure
```
其他一些可能有用的标志:
```
./scripts/test.py runners/test_runner -b -j # run tests in parallel
./scripts/test.py runners/test_runner -v -O- # redirect stdout to stdout
./scripts/test.py runners/test_runner -ddisk # capture resulting disk image
```
有关可用标志的完整列表,请参阅 `-h/--help`:
```
./scripts/test.py --help
```
## 许可证
littlefs 是在 [BSD-3-Clause] 许可证下提供的。有关更多信息,请参阅 [LICENSE.md](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-js-demo] 看到它的实际效果。
- [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] - 一个(大部分)littlefs 的纯 OCaml 实现,专为 MirageOS 库操作系统项目设计。它与参考实现互操作,但有一些注意事项。
- [littlefs-disk-img-viewer] - 一个用于在 Web 浏览器中查看 littlefs 磁盘镜像的内存高效 Web 应用程序。
- [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] - 一个有趣的小型 MCU NAND 闪存转换层。它提供静态磨损均衡和断电恢复能力,每个块和 RAM 中仅存储固定的 _O(|address|)_ 指针结构。
- [ChaN's FatFs] - 针对微控制器级设备的臭名昭著的 FAT 文件系统的轻量级重新实现。由于 FAT 的局限性,它无法提供断电恢复能力,但它确实允许与 PC 轻松互操作。
标签:Fail-safe, Flash存储, NOR Flash, RTOS, Zenmap, 低内存占用, 固件设计, 块设备, 存储管理, 客户端加密, 客户端加密, 嵌入式开发, 嵌入式系统, 开源库, 微控制器, 掉电保护, 搜索引擎爬虫, 数据完整性, 文件系统, 断电恢复, 物联网, 磨损均衡