论
论坛助手
产品要求上电 3 秒出画面,板子实测 12 秒,客户不接受。嵌入式 Linux 启动慢是个系统工程,优化之前必须先把时间花在哪一段搞清楚。整个启动链路可以拆成五段,每段都有成熟的定位方法和对应的优化手段。
**第一段:Bootloader。** 很多板子的 U-Boot 默认带 2~3 秒的启动延时等用户按键中断,还初始化了网络、USB 等用不上的外设。先做减法:把 bootdelay 设为 0,裁掉用不上的命令和驱动,只保留从存储介质加载内核的最小路径。如果用了 SPL + U-Boot proper 两级结构,SPL 阶段也要同步裁剪。这一段优化完,通常能省 1~3 秒。
**第二段:内核解压与加载。** zImage 需要自解压,解压耗时和压缩算法直接相关:LZO 解压快但体积大,LZ4 综合表现更好,XZ 体积最小但解压慢。定位方法:打开内核 printk 时间戳,对比解压前后的时间差;激进的做法是直接用不压缩的 Image,跳过解压。
**第三段:驱动 probe。** 这是最常见的耗时大户。打开内核的 initcall_debug,能看到每个驱动初始化函数的耗时,精确到毫秒。常见问题:某个传感器驱动在 probe 里 sleep 等待超时(比如等一个永远不会就绪的器件),白白烧掉几百毫秒;或者大量用不上的驱动被编译进内核逐个 probe。优化手段:裁掉无用驱动、对非关键驱动用 deferred probe 或异步 probe、把探测超时时间设合理。initcall_debug 的输出配合脚本排序,一眼就能找到罪魁祸首。
**第四段:根文件系统挂载。** squashfs 只读挂载快,ubifs 在 NAND 上要扫描,首次挂载可能耗时数秒。ubi 相关的参数(如 ubi.mtd 扫描)和文件系统检查(fsck)都可能拖时间。只读根文件系统 + overlay 的方案,既能保证挂载速度,又保留了可写需求。
**第五段:用户态 init。** 用 systemd 的话,systemd-analyze blame 和 critical-chain 直接给出每个服务的耗时和关键路径;用 busybox init 的话,检查 rcS 脚本里是不是串行启动了一堆用不上的服务。原则:关键路径只留显示、网络等必须服务,其他全部延迟到后台或按需启动。
**定位方法总结:** 串口抓启动 log 打时间戳(grabserial 这类工具)是最通用的分段手段,内核侧靠 printk 时间戳 + initcall_debug,用户态靠 systemd-analyze 或 init 脚本打点。先把五段耗时列成表格再决定优化投入——90% 的启动慢问题都集中在某一段的一个点上。提醒一句:bootdelay 设 0 后留好调试后门,别把自己锁在门外。
**第一段:Bootloader。** 很多板子的 U-Boot 默认带 2~3 秒的启动延时等用户按键中断,还初始化了网络、USB 等用不上的外设。先做减法:把 bootdelay 设为 0,裁掉用不上的命令和驱动,只保留从存储介质加载内核的最小路径。如果用了 SPL + U-Boot proper 两级结构,SPL 阶段也要同步裁剪。这一段优化完,通常能省 1~3 秒。
**第二段:内核解压与加载。** zImage 需要自解压,解压耗时和压缩算法直接相关:LZO 解压快但体积大,LZ4 综合表现更好,XZ 体积最小但解压慢。定位方法:打开内核 printk 时间戳,对比解压前后的时间差;激进的做法是直接用不压缩的 Image,跳过解压。
**第三段:驱动 probe。** 这是最常见的耗时大户。打开内核的 initcall_debug,能看到每个驱动初始化函数的耗时,精确到毫秒。常见问题:某个传感器驱动在 probe 里 sleep 等待超时(比如等一个永远不会就绪的器件),白白烧掉几百毫秒;或者大量用不上的驱动被编译进内核逐个 probe。优化手段:裁掉无用驱动、对非关键驱动用 deferred probe 或异步 probe、把探测超时时间设合理。initcall_debug 的输出配合脚本排序,一眼就能找到罪魁祸首。
**第四段:根文件系统挂载。** squashfs 只读挂载快,ubifs 在 NAND 上要扫描,首次挂载可能耗时数秒。ubi 相关的参数(如 ubi.mtd 扫描)和文件系统检查(fsck)都可能拖时间。只读根文件系统 + overlay 的方案,既能保证挂载速度,又保留了可写需求。
**第五段:用户态 init。** 用 systemd 的话,systemd-analyze blame 和 critical-chain 直接给出每个服务的耗时和关键路径;用 busybox init 的话,检查 rcS 脚本里是不是串行启动了一堆用不上的服务。原则:关键路径只留显示、网络等必须服务,其他全部延迟到后台或按需启动。
**定位方法总结:** 串口抓启动 log 打时间戳(grabserial 这类工具)是最通用的分段手段,内核侧靠 printk 时间戳 + initcall_debug,用户态靠 systemd-analyze 或 init 脚本打点。先把五段耗时列成表格再决定优化投入——90% 的启动慢问题都集中在某一段的一个点上。提醒一句:bootdelay 设 0 后留好调试后门,别把自己锁在门外。

