Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
littlefs
关于littlefs文件系统的效率问题
发布于 2019-12-26 14:11:33 浏览:9287
订阅该版
最近在使用littlefs文件系统,由于要跟原系统做兼容 没有使用FAL接口及MTD设备,直接使用lfs操作的块设备, 从官方的资料来看,littlefs有点还是很明显的, 占用资源少,自带磨损均衡等等。。。 移植完成后,测试lfs系统挂载及读写操作都没有问题, 但执行效率极慢,连最基本的ls命令都是一个一个的出, 而同样的工程,换成FAT系统,就完全不一样,效果如下 使用littlefs时的效果 ![ls.gif](/uploads/201912/26/140152ahsmoe4mhj4x4dhx.gif) 使用fat时的效果 ![ls2.gif](/uploads/201912/26/140902m2x50raalcixf2c2.gif) 文件使用的是同一个工程,底层SPI驱动都是完全一样的, 不知道为什么会差别这么大, 而且使用littlefs时,读写文件达到几K时,经常会引起系统重启, 具体原因未知,还在查找中
查看更多
17
个回答
默认排序
按发布时间排序
通宵敲代码
2020-01-03
这家伙不懒,他只是什么都不想写
为了验证littlefs的读写测试策略,我尝试进行了如下测试, 并将测试过程中littlefs对SPI Flash的所有操作全部打印了出来,然后进行了分析。 测试用到的代码如下(其中addr初始化的值需要每次手动更改) ``` const char spi_test[] = "LittleFS - A high-integrity embedded file system "; char test[256]; u32 i, cnt = 0; u32 addr1=8192; int fd; fd = open("LittleFS.bin", O_WRONLY | O_CREAT, 0); for(i=0;i<4;i++) { rt_kprintf("SPI Flash write time #%d -- %d\n",i , rt_tick_get()); rt_snprintf(test, sizeof(test), "%s -- %d", spi_test, rt_tick_get()); lseek(fd, addr1, SEEK_SET); write(fd, (u8 *)test, sizeof(test)); addr1 += sizeof(test); } close(fd); addr1 = 0; fd = open("LittleFS.bin", O_RDONLY, 0); for(i=0;i<36;i++) { rt_kprintf("SPI Flash read time #%d -- %d\n",i , rt_tick_get()); lseek(fd, addr1, SEEK_SET); read(fd, (u8 *)test, sizeof(test)); addr1 += sizeof(test); } close(fd); ``` ## 具体的测试步骤如下: ### 第一次测试 新建文件LittleFS.bin,从文件0地址处开始,写入四次数据,每次256字节 - 前两次写入时,写入块地址 —— 0x75F000,写入数据重复 “LittleFS -- 177” - 第三次写入时,写入块地址 —— 0x760000,先复制0x75F000处的两次数据到0x760000,再写入第三次的数据 “LittleFS -- 203” - 第四次写入时,写入块地址 —— 0x761000,先复制0x760000处的两次数据到0x761000,再写入第四次的数据 “LittleFS -- 228 - 写入结束,文件大小1024Byte,存储块在0x761000处 ### 第二次测试 从文件LittleFS.bin 4096地址处开始,写入四次数据,每次256字节 - 第一次写入,写入块地址 —— 0x783000,先复制0x761000处的四次数据到0x783000,然后从0x783400处写入3072Byte,填充数据到0x783FFF,再从0x784000处开始,写入本次的数据,然而数据丢失,只写入“?” - 第二次写入,写入块地址 —— 0x785000,先复制0x784000处的一次数据到0x785000,再写入第二次的数据 “LittleFS -- 281” - 第三次写入,写入块地址 —— 0x786000,先复制0x785000处的两次数据到0x785000,再写入第三次的数据 “LittleFS -- 309” - 第四次写入,写入块地址 —— 0x787000,先复制0x786000处的三次数据到0x785000,再写入第四次的数据 “LittleFS -- 343” - 写入结束,文件大小5120Byte,存储块在0x783000->0x787000处 ### 第三次测试 从文件LittleFS.bin 5120地址处开始,写入四次数据,每次256字节 - 第一次写入,写入块地址 —— 0x6B7000,先复制0x787000处的四次数据到0x6B7000,再从0x6B7400处开始,写入本次的数据 “LittleFS -- 190” - 第二次写入,写入块地址 —— 0x6B8000,先复制0x6B7000处的五次数据到0x6B8000,再写入第二次的数据 “LittleFS -- 248” - 第三次写入,写入块地址 —— 0x6B9000,先复制0x6B8000处的六次数据到0x6B9000,再写入第三次的数据 “LittleFS -- 304” - 第四次写入,写入块地址 —— 0x6BA000,先复制0x6B9000处的七次数据到0x6BA000,再写入第四次的数据 “LittleFS -- 366” - 写入结束,文件大小6144Byte,存储块在0x783000->0x6BA000处 ### 第四次测试 从文件LittleFS.bin 8192地址处开始,写入四次数据,每次256字节 - 第一次写入,写入块地址 `—— 0x5DD000`,先复制`0x6BA000`处的八次数据到0x5DD000,然后从0x5DD800处写入3072Byte,填充数据到0x5DDFFF,再从0x5DE000处开始,写入本次的数据,然而数据丢失,只写入“?” - 第二次写入,写入块地址 —— 0x5DF000,先复制0x5DE000处的一次数据到0x5DF000,再写入第二次的数据 `“LittleFS -- 315”` - 第三次写入,写入块地址 —— 0x5E0000,先复制0x5DF000处的两次数据到0x5E0000,再写入第三次的数据 `“LittleFS -- 344”` - 第四次写入,写入块地址 —— 0x5E1000,先复制0x5E0000处的三次数据到0x5E1000,再写入第四次的数据 `“LittleFS -- 376”` - 写入结束,文件大小9216Byte,存储块在`0x783000->0x5DD000->0x5E1000`处 ### 第五次测试 - 分36次,完全读出LittleFS.bin文件内容,对比操作地址与内容,与上面描述一致 附上测试过程输出的日志文件,感兴趣的可以看看 [attach]13098[/attach] ## 总结一下: 1、littlefs文件系统初始化时,会在SPI Flash最开始的两个块中格式化出两个超级块,用于对文件系统的识别及根目录的索引; 2、在建立文件或目录时,littlefs会从超级块中分配一个页用于记录文件的基本信息,并建立文件数据的索引以找到文件的具体数据内容; 3、当文件大小小于一个块尺寸时,尽管文件系统不对超出的部分引索,但其他文件仍然不能使用这个块的剩余部分,所以一个文件至少占用一个块尺寸; 4、如果写入到文件中的数据超过一个块尺寸时,文件系统会在各个块中建立联系,确保数据的联系性,但各个块在物理地址上不一定连续; 5、当在一个文件中追加数据时,文件系统会复制源文件中最后不足一个块的数据到一个新的块,然后在新的块中追加要写入的数据,也就是littlefs的“磨损均衡”; 6、接上边第五条,在数据写入时,littlefs每次都会新开辟一个数据块,然后在新的数据块中添加要写入的数据,即便是对原文件覆盖写入也同样开辟一个新的块,待整个块写满或数据写完时才更新文件索引,让新的数据块在文件链路中生效, 由于数据写入的较慢,而索引更新只需一次写入即可,所以littlefs能实现“断电恢复”。
otter
2022-06-06
这家伙很懒,什么也没写!
楼主的帖子真的非常详细,细看了一下littlefs的设计文档,楼主的结果和设计文档的描述感觉非常移植。 littlefs使用的是COW(写时拷贝)的设计。并且使用的前向指针来链接文件。所以任何文件修改,都会导致修改位置以及往后的位置的flash块需要分配新块,并将更新后的块内容拷贝到新块(需要更新后面链表的指针)。这样的结果就是小改动导致了大量的拷贝。 所以littlefs只适合做增量写入的操作(日志记录),不适合做频繁改动的操作。
通宵敲代码
2019-12-26
这家伙不懒,他只是什么都不想写
在SPI读写函数中优化掉下面这条代码, 效果有所改善,但还是不尽人意,继续优化。 优化掉的代码 [attach]12922[/attach] 测试效果 ![110,0](https://www.rt-thread.org/qa/forum.php?mod=image&aid=12921&size=300x300&key=1735f7a1f6b33dff&nocache=yes&type=fixnone)
通宵敲代码
2019-12-26
这家伙不懒,他只是什么都不想写
用示波器抓去了一下数据读写的波形, 同样是往SPI Flash写入一个2K(2018Byte)的文件, 需要的时间差别还是挺大的, 待写入的文件,随机写入的一串数字 [attach]12928[/attach] littlefs文件系统需要的时间,差不多用了900ms, 而且测试发现,文件重复写入时需要的时间会更长 [attach]12929[/attach] 相比之下,fat文件系统只用了不到300ms [attach]12930[/attach] 差距还是蛮大的
xdj999
2019-12-26
这家伙很懒,什么也没写!
建议用fal 转mtd,我用的好像速度没问题
通宵敲代码
2019-12-27
这家伙不懒,他只是什么都不想写
>建议用fal 转mtd,我用的好像速度没问题 --- 嗯嗯,下一步准备试试
通宵敲代码
2019-12-31
这家伙不懒,他只是什么都不想写
附上两个帖子,看来不止一位朋友遇到了这个问题 有人提出是sync函数的问题,有机会查查看 [https://blog.csdn.net/at91rm9200/article/details/86748855](https://blog.csdn.net/at91rm9200/article/details/86748855) [https://www.amobbs.com/thread-5717005-1-1.html](https://www.amobbs.com/thread-5717005-1-1.html)
通宵敲代码
2020-01-03
这家伙不懒,他只是什么都不想写
附上两个mbed论坛关于littlefs读写问题的问答,有关细节的资料,可以参考下源文件中的**DESIGN.md**跟**SPEC.md**,目前我也还在研究中 第一个是关于文件覆盖写入的问题 [https://forums.mbed.com/t/littlefs-behaves-strangely/6516](https://forums.mbed.com/t/littlefs-behaves-strangely/6516) 当在一个现有的文件中重新写入数据时,会另外开辟新的Flash块, 在新的Flash块中将数据写完之后,会将原先的块做“丢弃”处理, 官方给的回答是正常,是为了做磨损均衡,应该也是为了断电保护; [attach]13088[/attach] 另外我还发现,在新块中写入数据是,也会将旧块中相对多出来的数据也复制到新块中, 导致我们写很少数据时,却在后台引起了大块数据的复制操作,可以看下面做的测试 [attach]13093[/attach]
通宵敲代码
2020-01-03
这家伙不懒,他只是什么都不想写
第二个是有人提问“littlefs性能不佳及读取频繁的问题” [https://forums.mbed.com/t/bad-performance-big-number-of-reads-when-using-littlefs/5855](https://forums.mbed.com/t/bad-performance-big-number-of-reads-when-using-littlefs/5855) 下面是用户提问及官方给出的回答, 感觉littlefs为了处理断电恢复及磨损均衡问题, 牺牲了很大的运行性能 [attach]13094[/attach]
hichard
认证专家
2020-01-03
这家伙很懒,什么也没写!
需要速度还是用Nand或者mmc卡。spi flash本身慢,littlefs为了安全也慢!
撰写答案
登录
注册新账号
关注者
4
被浏览
9.3k
关于作者
通宵敲代码
这家伙不懒,他只是什么都不想写
提问
8
回答
25
被采纳
0
关注TA
发私信
相关问题
1
dfs_mount挂载文件系统路径的路径必须为‘/’才能成功
2
romfs无法执行df命令
3
w25q128挂载littlefs出现assert failed?
4
使用littlefs出现Corrupted dir pair at 1 0
5
使用片上flash的 littlefs 无法创建多个目录
6
littlefs挂载总是在lfs.c文件中 LFS_ASSERT
7
littlefs文件系统卡顿问题
8
需要littlefs 挂载在片上flash
9
日志存储是使用fat如何做磨损平衡?
10
挂载littlefs文件系统的flash寿命计算方式?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
【NXP-MCXA153】 定时器驱动移植
2
GD32F450 看门狗驱动适配
3
【NXP-MCXA153】看门狗驱动移植
4
RT-Thread Studio V2.2.9 Release Note
5
CherryUSB的bootuf2配置
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
freemodbus
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
7
个答案
2
次被采纳
a1012112796
15
个答案
1
次被采纳
Ryan_CW
5
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
本月文章贡献
YZRD
3
篇文章
6
次点赞
catcatbing
3
篇文章
6
次点赞
lizimu
2
篇文章
8
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部