从引导程序到根文件系统的性能观察方法自己动手搭建一套嵌入式 Linux 系统从 U-Boot 编译、内核裁剪到 Buildroot/Yocto 构建 rootfs最具有成就感的时刻莫过于终端打印出 Login 提示符。但系统能跑起来和性能达标完全是两码事。开机花了 15 秒还是 2.5 秒根文件系统吃掉了 128MB 还是 12MB Flash内存刚启动就占用了 80%缺少量化的基准测试与指标解读系统的优化调整就只能盲目摸黑。1. 口径统一建立启动时间与资源开销的度量线衡量一套嵌入式 Linux 系统搭建得好不好不能只凭感官上的“挺快”。必须拆解出四个确切的物理指标分阶段启动耗时 (Stage Boot Latency)SPL/ROM Code ➔ U-Boot ➔ Kernel Decompress Init ➔ Userland init ➔ 目标应用主线程就绪各个阶段精确耗时多少毫秒静止内存驻留集 (Static PSS/RSS)系统进入 Idle 状态后内核空间Kernel Slabs与用户态进程实际消耗了多少物理内存文件系统读取吞吐 (Storage Read Throughput)SquashFS/UBIFS/ext4 在 NAND/eMMC 上的顺序与随机 4K 读取带宽是多少根文件系统瘦身尺寸 (RootFS Footprint)剔除冗余动态库后镜像文件物理体积控制在多少兆2. 启动耗时捕获串口时间戳与 GPIO 探针打点测量启动耗时最准确的方法不是依靠系统启动完成后的uptime命令而是在开发机侧通过grabserial工具捕获串口打印的时间戳配合芯片 GPIO 引脚电平翻转进行双重校验。使用grabserial工具对板卡串口输出进行毫秒级基准测量$ python3 -m grabserial -v -d /dev/ttyUSB0 -b 115200 -t -m U-Boot SPL* [0.000000 0.000000] U-Boot SPL 2024.04 (Aug 18 2026 - 10:00:00 0800) [0.124102 0.124102] Loading Image from MMC1 ... [0.472015 0.347913] Starting Kernel ... [0.952104 0.480089] [ 0.000000] Linux version 6.6.21 (buildhost) ... [1.572110 0.620006] [ 0.620000] Run /sbin/init as main process [1.962125 0.390015] [APP_READY] Target Application Initialized Successfully!通过这套串口时间戳数据启动阶段被清晰拆解U-Boot 阶段耗时472ms - 124ms 348ms内核加载与 Probe 阶段耗时1572ms - 472ms 1100ms用户态 init 至应用就绪耗时1962ms - 1572ms 390ms系统总冷启动耗时1.962 秒3. 内存与 IO 基准测试fio 与 smem 分析脚本在 RootFS 启动后需要使用标准的工具评估存储读写性能与内存分配。下面的 Shell 自动化脚手架示范了如何在嵌入式单板上通过fio和smem工具提取根文件系统读写吞吐与 PSS 内存分布#!/bin/bin/sh echo echo 嵌入式 Linux 性能基准自动化测试 echo # 1. 检查根文件系统读取吞吐 (SquashFS / eMMC) echo [1/3] 测量文件系统 4K 随机读取性能... fio --namerandom-read \ --ioenginesync \ --rwrandread \ --bs4k \ --numjobs1 \ --size10M \ --runtime10 \ --time_based \ --filename/tmp/test_fio.dat \ --minimal | awk -F; {printf 4K RandRead IOPS: %s, Bandwidth: %d KB/s\n, $8, $7} rm -f /tmp/test_fio.dat # 2. 测量内核 Memory PSS / RSS 比例 (使用 smem) echo [2/3] 提取用户态进程 PSS 内存分布... if command -v smem /dev/null 21; then smem -t -k -s pss | tail -n 10 else echo 提示: smem 未安装回退至 proc/meminfo 分析 cat /proc/meminfo | grep -E MemTotal|MemFree|MemAvailable|Slab|Buffers|Cached fi # 3. 提取内核 Slab 缓冲区分配 echo [3/3] 检查前 5 大 Kernel Slab 内存开销... cat /proc/slabinfo | awk NR2 {print $1, $2*$3} | sort -n -k2 -r | head -n 5通过执行这个测试脚本可以获得确凿的数据如果发现4K RandRead Bandwidth只有 1.2 MB/s说明内核 MMC 驱动未开启 High-Speed 模式或者 SDHCI 时钟频率被错误拉低如果MemAvailable偏低且Slab中的dentry/inode_cache占据了大半内存则提示内核编译时需要裁剪掉不必要的扩展文件系统支持。4. 优化对比与数据解读根据基准测试拿到的数据裁剪优化有了明确的方向指标初始搭建版本 (Raw Buildroot)深度裁剪优化后版本优化动作手段总启动耗时6.8 秒1.8 秒U-Boot 开启CONFIG_SKIP_LOWLEVEL_INIT内核移除控制台冗余printkinit 换为轻量级runitRootFS 体积48.2 MB8.4 MBC 库由 glibc 切换为 musl-libc剥离strip调试符号开启 SquashFS XZ 压缩Memory PSS32.4 MB9.1 MB内核裁剪掉不必要的 Network Protocols (IPv6/BT/NFC)关闭 Tracing/Debug 选项看懂 performance 数据是嵌入式 Linux 搭建从“成功点亮”迈向“生产可用”的必经之路。数据在哪里瓶颈就在哪里用精准的测试结果指导裁剪才能打造出极简高效的系统。