第1章:文件系统选择与优化

做嵌入式Linux回测系统,我踩过最大的坑就是文件系统。说实话,很多人觉得文件系统就是个存数据的地方,随便选一个就行。但在我参与的几个高性能回测项目中,文件系统选型直接决定了系统能不能跑起来。

今天咱们就聊聊Flash友好型文件系统、只读文件系统,还有日志策略怎么调优。这些都是我这些年摸爬滚打总结出来的经验。

1.1 Flash友好型文件系统:UBIFS vs JFFS2

嵌入式设备用的都是Flash存储,不是机械硬盘。Flash有个特点:写前必须先擦除,而且擦除次数有限。普通文件系统(比如ext4)在Flash上跑,很快就会把Flash写坏。

所以我们需要Flash友好型文件系统。目前主流的就是UBIFS和JFFS2。

1.1.1 JFFS2:老牌选手

JFFS2是Linux内核里最早出现的Flash文件系统之一。它的设计思路很直接:把整个Flash当成一个日志,所有修改都追加写入。

我在一个早期的回测项目里用过JFFS2。当时觉得它挺稳定,但后来发现一个问题——挂载时间太长了。你想想看,每次挂载都要扫描整个Flash,重建文件系统树。如果Flash有128MB,挂载时间可能超过10秒。

JFFS2核心特点:

  • 支持磨损均衡
  • 支持压缩
  • 挂载时间随容量线性增长
  • 内存占用较高

1.1.2 UBIFS:新一代选择

UBIFS是JFFS2的接班人。它引入了UBI层来处理坏块管理和磨损均衡,性能比JFFS2好很多。

我个人习惯在回测系统里用UBIFS。为什么?因为它挂载快,而且支持写缓冲,写入性能比JFFS2高出好几倍。

# 创建UBIFS镜像
mkfs.ubifs -r rootfs -m 2048 -e 128KiB -c 1024 -o ubifs.img

# 制作UBI镜像
ubinize -o ubi.img -m 2048 -p 128KiB ubinize.cfg

# 挂载UBIFS
ubiattach -m 1 -d 0 /dev/ubi_ctrl
mount -t ubifs ubi0:rootfs /mnt/rootfs

我的建议:新项目直接用UBIFS。JFFS2只适合Flash容量很小(64MB以下)的场景。

1.2 只读文件系统:SquashFS

回测系统的固件部分,其实不需要频繁修改。这时候用只读文件系统就非常合适。

SquashFS是我最常用的只读文件系统。它支持高压缩比,能把一个100MB的根文件系统压缩到30MB左右。对于Flash容量有限的嵌入式设备来说,这太重要了。

我曾经在一个项目里,固件大小刚好超过Flash容量。用SquashFS压缩后,不仅塞进去了,还省出20MB空间给数据分区。

# 制作SquashFS镜像
mksquashfs rootfs/ rootfs.squashfs -comp xz -b 128K

# 挂载SquashFS
mount -t squashfs rootfs.squashfs /mnt/rootfs -o loop

注意:SquashFS是只读的。如果需要修改文件,必须重新制作镜像并烧录。所以它只适合存放不常变动的系统文件。

1.3 日志策略调优

文件系统的日志机制,说白了就是为了保证数据一致性。但日志写多了,性能就会下降。

在回测场景下,我们通常可以接受一定的数据丢失风险,换取更高的写入性能。这时候就可以调整日志策略。

1.3.1 UBIFS日志调优

UBIFS的日志策略主要通过挂载参数来控制:

参数 说明 推荐值
bulk_read 批量读取,提高顺序读性能 1
no_chk_data_crc 跳过数据CRC校验,提高写性能 1(回测场景)
compr_type 压缩类型,lzo速度最快 lzo
# 高性能挂载方式
mount -t ubifs ubi0:rootfs /mnt/rootfs -o bulk_read,no_chk_data_crc,compr_type=lzo

1.3.2 关闭不必要的日志

对于临时数据分区,比如存放回测中间结果的目录,可以考虑关闭日志:

# 创建无日志的UBIFS卷
ubimkvol /dev/ubi0 -N temp_data -s 50MiB -t static

# 挂载时禁用日志
mount -t ubifs ubi0:temp_data /mnt/temp -o chk_data_crc=0

避坑指南:我曾经在一个回测系统里,把所有分区都关了日志。结果一次意外断电后,配置文件损坏,系统起不来了。所以系统关键分区(比如/etc)一定要保留日志保护。

1.4 知识体系总览

下面这张图展示了本章的核心逻辑:

文件系统选择与优化知识体系 文件系统选型 Flash友好型文件系统 只读文件系统 日志策略调优 JFFS2 UBIFS SquashFS UBIFS参数 关闭日志 核心原则:根据读写频率、数据重要性、性能需求选择 系统分区用SquashFS + 数据分区用UBIFS

1.5 实战建议

说了这么多,最后给几个实际项目中的建议:

  1. 系统分区用SquashFS:固件、内核、库文件放这里,只读保护,压缩省空间。
  2. 数据分区用UBIFS:回测结果、配置文件、日志文件放这里,需要读写。
  3. 临时分区关日志:中间计算结果、缓存文件,丢了也不心疼。
  4. 关键配置保留日志:比如网络配置、系统参数,这些丢了系统可能起不来。

小技巧:如果你用的是NAND Flash,记得选UBIFS。如果是NOR Flash,JFFS2可能更合适。不过现在大部分嵌入式设备都是NAND了。

嗯,文件系统这块就聊到这儿。记住一句话:没有最好的文件系统,只有最适合你场景的文件系统。选对了,性能翻倍;选错了,天天修Bug。


公众号:蓝海资料掘金营,微信deep3321