
根文件系统瘦身优化与开机速度提升方案嵌入式设备开机等30秒用户以为它坏了开机3秒进入系统用户觉得这设备真快。这就是优化的价值——不是炫技是体验。引言在资源受限的嵌入式设备上根文件系统的体积和启动速度直接影响用户体验和产品成本。一个臃肿的 rootfs 浪费 Flash 空间一个缓慢的启动过程消耗用户耐心。本文将系统讲解根文件系统的瘦身方法和开机速度优化方案。一、根文件系统瘦身1.1 瘦身前的体积分析优化第一步先搞清楚肉长在哪了# 查看根文件系统总大小du-shrootfs/# 查看各目录大小排序du-shrootfs/*|sort-rh# 查看前20大文件findrootfs/-typef-execdu-h{}|sort-rh|head-20典型体积分布目录/文件典型大小占比优化潜力/lib/libc.so1.5MB25%中/bin/busybox1.6MB27%中/usr/lib/*.so1.0MB17%高/lib/modules/0.8MB13%高/etc/0.1MB2%低其他1.0MB16%中1.2 库文件精简移除不必要的库# 查找根文件系统中所有动态库findrootfs/-name*.so*-execls-lh{}# 检查哪些库没有被任何程序引用# 先找出所有程序的NEEDED依赖findrootfs/-typef-executable-exec\arm-linux-gnueabihf-readelf-d{}\;2/dev/null|grepNEEDED|\sort-u|awk-F[][]{print $2}/tmp/needed_libs.txt# 对比实际存在的库找出多余的findrootfs/-namelib*.so*-execbasename{}\;|\sort-u/tmp/actual_libs.txtcomm-23/tmp/actual_libs.txt /tmp/needed_libs.txt# 输出的就是可以安全删除的库使用 musl libc 替代 glibcglibc 体积大、功能全但对很多嵌入式场景来说过于臃肿。musl libc 是更轻量的替代方案特性glibcmusllibc.so 体积~1.5MB~400KB功能完整性完整够用偶有兼容性问题性能高中等适用场景通用资源受限设备在 Buildroot 中切换Toolchain --- C library (musl) # 选择 musl 替代 glibc裁剪 locale 和 charmapglibc 默认包含大量 locale 数据很多嵌入式设备用不到# 查看locale数据大小du-shrootfs/usr/lib/locale/du-shrootfs/usr/share/i18n/# 如果不需要国际化支持直接删除rm-rfrootfs/usr/lib/locale/rm-rfrootfs/usr/share/i18n/rm-rfrootfs/usr/share/locale/1.3 BusyBox 裁剪重新配置 BusyBox移除不需要的 appletmakemenuconfig# 可考虑移除的模块根据实际需求Applets ---[]Mail utilities# 邮件工具嵌入式基本不用[]Print utilities# 打印工具[]Radio utilities# 收音机工具[]Linux Ext2 FS Progs# ext2工具用ext4的话不需要[]RAID utilities# RAID工具1.4 内核模块精简# 查看已安装的内核模块findrootfs/lib/modules/-name*.ko|xargsls-lh|sort-k5-rh# 移除不常用的驱动模块需根据硬件配置决定# 例如移除不必要的文件系统支持rmrootfs/lib/modules/*/kernel/fs/nfs/rmrootfs/lib/modules/*/kernel/fs/cifs/rmrootfs/lib/modules/*/kernel/fs/isofs/# 删除模块的依赖信息和源码符号rmrootfs/lib/modules/*/buildrmrootfs/lib/modules/*/source1.5 使用 SquashFS 压缩如果根文件系统不需要写入使用 SquashFS 压缩可以大幅减小体积# 使用 xz 压缩最高压缩率mksquashfs rootfs/ rootfs.squashfs-compxz -Xdict-size100%# 对比压缩效果du-shrootfs/# 原始大小ls-lhrootfs.squashfs# 压缩后大小典型压缩效果压缩算法原始大小压缩后压缩率无压缩6.0MB6.0MB100%gzip6.0MB2.8MB47%xz6.0MB1.9MB32%1.6 瘦身效果汇总优化措施优化前优化后节省原始 rootfs8.0MB——移除多余库8.0MB6.5MB1.5MBglibc→musl6.5MB5.0MB1.5MBBusyBox裁剪5.0MB4.2MB0.8MB模块精简4.2MB3.5MB0.7MBSquashFS压缩3.5MB1.5MB2.0MB总计8.0MB1.5MB6.5MB二、开机速度优化2.1 启动时间测量首先量化启动各阶段耗时# 方法一内核 bootgraph# 在 bootargs 中添加 initcall_debug# initcall_debug loglevel8# 内核启动后查看cat/sys/kernel/debug/bootgraph/databootgraph.txt# 使用 scripts/bootgraph.pl 生成可视化图# 方法二使用 systemd-analyze如果用systemdsystemd-analyzetimesystemd-analyze blame# 方法三在 rcS 脚本中加时间戳echo[$(date%s.%N)] Step: mount proc/var/log/boot.log典型启动时间分布阶段典型耗时优化空间Bootloader2~5s中内核解压0.5~2s中内核初始化1~3s高根文件系统挂载0.5~5s高init/rcS 执行1~5s高首个应用启动0.5~2s中总计5~22s—2.2 Bootloader 阶段优化# U-Boot 中优化项# 1. 跳过不必要的探测setenv scanusb no# 跳过USB扫描setenv scandm no# 跳过DMA扫描# 2. 减少等待时间setenv bootdelay0# 启动延迟设为0秒saveenv# 3. 使用 fastboot 机制# 禁用环境变量从存储加载直接使用编译时默认值setenv loadenv no2.3 内核阶段优化# 1. 精简内核配置移除不需要的驱动makemenuconfig# 关闭调试信息# CONFIG_DEBUG_INFO is not set# 关闭不必要的文件系统# CONFIG_NFS_FS is not set# 关闭不需要的总线驱动# 2. 内置关键驱动避免模块加载延迟# 将启动必需的驱动从模块(M)改为内置(*)# 例如: MMC驱动、串口驱动、Flash驱动# 3. 使用 lz4 压缩内核解压最快# CONFIG_KERNEL_LZ4y内核压缩方式对比压缩方式镜像大小解压速度综合启动时间gzip中中中lz4大最快最短xz最小慢较长zstd小快短2.4 根文件系统挂载优化# 1. JFFS2 → UBIFS挂载速度快10倍以上# JFFS2挂载128MB需要10sUBIFS只需0.5s# 2. ext4 挂载参数优化# 在 fstab 中使用 noatime 参数# /dev/mmcblk0p2 / ext4 noatime,errorsremount-ro 0 1# 3. 禁用文件系统日志牺牲掉电安全换取速度tune2fs-O^has_journal /dev/mmcblk0p2# 4. 使用 squashfs 只读文件系统挂载最快2.5 init 脚本优化这是优化收益最大的部分。原始 rcS 脚本通常是串行执行的改为并行可以大幅加速。优化前串行执行#!/bin/shmount-tproc proc /proc# 0.1smount-tsysfs sysfs /sys# 0.1smdev-s# 0.5sifconfigeth0192.168.1.100 up# 1.0shwclock-s# 0.3sdropbear-R-p22# 0.5smount-a# 0.2s# 总计: 2.7s优化后并行延迟启动#!/bin/sh# 关键路径最小化阻塞时间# 快速挂载虚拟文件系统mount-tproc proc /procmount-tsysfs sysfs /sysmount-tdevtmpfs devtmpfs /dev# mdev 后台启动echo/sbin/mdev/proc/sys/kernel/hotplug mdev-s# 网络配置后台执行(ifconfig eth0192.168.1.100 up;\routeadddefault gw192.168.1.1)# 非关键服务延迟启动(sleep2dropbear-R-p22)# 跳过 RTC 同步用网络时间同步替代# hwclock -s # 注释掉echoSystem Ready2.6 使用 initramfs 加速启动将根文件系统加载到内存中运行消除存储 I/O 延迟# 1. 制作 initramfsfindrootfs/|cpio-Hnewc-o|gzipinitramfs.cpio.gz# 2. 将 initramfs 编译进内核makemenuconfig# General setup ---# [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support# (initramfs.cpio.gz) Initramfs source file(s)# 3. 内核启动后直接在内存中运行无需挂载存储initramfs 方案的取舍优势代价启动极快无存储I/O占用RAMrootfs大小无磨损纯内存操作掉电丢失需配合持久化文件读取零延迟修改需重新打包2.7 Read-Ahead 预读优化# 增大预读值减少存储读取次数blockdev--setra4096/dev/mmcblk0# 在 rcS 中永久设置echo4096/sys/block/mmcblk0/queue/read_ahead_kb三、优化效果验证3.1 启动时间测量脚本#!/bin/sh# /usr/bin/boottime.sh — 放在 rcS 最后执行END_TIME$(cat/proc/uptime|awk{print $1})echoechoBoot completed in${END_TIME}secondsecho# 写入持久化日志echo$(date): Boot time:${END_TIME}s/var/log/boottime.log3.2 优化前后对比优化阶段启动时间优化措施优化前22.3s无Bootloader优化18.5sbootdelay0跳过扫描内核精简14.2s内置驱动lz4压缩JFFS2→UBIFS10.1s挂载时间 8s→0.5srcS并行优化6.8s服务并行延迟启动initramfs3.2s内存运行零I/O总优化3.2s从22.3s降至3.2s四、优化注意事项先测量再优化不要凭感觉优化用数据说话一次只改一处同时改多处无法判断哪项有效稳定性优先不能为了快牺牲系统稳定性留好退路每次优化前备份可用的 rootfs 镜像考虑实际场景不是所有优化都适用于你的硬件需结合实际情况总结根文件系统的优化分两条线瘦身减体积和提速减时间。瘦身的核心手段是更换轻量库musl、裁剪不需要的模块和命令、使用 SquashFS 压缩。提速的关键在于三个层面内核层精简内置驱动快速解压、挂载层UBIFS替代JFFS2、服务层并行启动延迟非关键服务。从22秒优化到3秒不是神话而是每一层都挤掉水分的结果。优化是一个迭代过程——测量、分析、优化、验证循环往复直到达到目标。