F
最近在做一个电力终端项目,要求固件体积尽量小,启动尽量快。从主线5.4内核开始裁剪,最后把zImage从12MB砍到了3MB以内,启动时间从8秒压到2秒。分享一下裁剪思路。
第一步:先搞清楚你的硬件
裁剪的前提是你知道板子上有什么芯片。我们的板子是:
- CPU:i.MX6ULL(Cortex-A7,单核,512MB DDR3)
- Flash:256MB NAND
- 外设:ETH、UART、SPI Flash、I2C RTC、USB Host
不需要的硬件驱动全部关掉,这是最大的一块。
第二步:关掉不相关的体系结构和特性
Processor type and features:
- 只选你的CPU型号,其他全部关掉
- SMP、NUMA、大内核锁这些不需要的都关
Power management:
- 只留必要的CPU idle,其他省电策略如果不需要就关
第三步:文件系统和驱动
File systems:
- 只留ext4和squashfs(我们用squashfs做根文件系统,只读压缩)
- NFS、FAT、NTFS、ISO9660全部关掉
Device Drivers:
- 网络设备:只留FEC以太网驱动
- USB:只留EHCI和USB Host, gadget、OTG都关
- I2C/SPI:只留你实际用的控制器
- 字符设备:tty、串口、rtc、watchdog,其他全关
- 块设备:NAND/MLC驱动留着,其他SATA、SD全部关
第四步:内核调试和开发选项
Kernel hacking里面的东西,发布版基本全关:
- printk如果不需要可以调低级别(或者直接关)
- dynamic debug、ftrace、kprobes全部关
- KGDB、kdump这些调试功能都关
裁剪前后对比
| 项目 | 裁剪前 | 裁剪后 |
|---|---|---|
| zImage大小 | 12.3 MB | 2.8 MB |
| 内核配置项 | ~15000 | ~3500 |
| 启动到shell | ~8s | ~2.1s |
| 运行内存占用 | ~80MB | ~35MB |
一个容易忽略的点:模块 vs 内建
很多人图方便把驱动都编成模块(.ko),但如果你的根文件系统在NAND上,加载模块的时间开销其实不小。对于必须的驱动,直接编进内核(y)比模块(m)启动更快。
我们最终把根文件系统相关的驱动(NAND、UBI、ext4)全部编进内核,其他外设驱动编成模块,按需加载。
大家做嵌入式Linux裁剪的时候,最小做到过多小?有没有什么独门技巧?
第一步:先搞清楚你的硬件
裁剪的前提是你知道板子上有什么芯片。我们的板子是:
- CPU:i.MX6ULL(Cortex-A7,单核,512MB DDR3)
- Flash:256MB NAND
- 外设:ETH、UART、SPI Flash、I2C RTC、USB Host
不需要的硬件驱动全部关掉,这是最大的一块。
第二步:关掉不相关的体系结构和特性
Processor type and features:
- 只选你的CPU型号,其他全部关掉
- SMP、NUMA、大内核锁这些不需要的都关
Power management:
- 只留必要的CPU idle,其他省电策略如果不需要就关
第三步:文件系统和驱动
File systems:
- 只留ext4和squashfs(我们用squashfs做根文件系统,只读压缩)
- NFS、FAT、NTFS、ISO9660全部关掉
Device Drivers:
- 网络设备:只留FEC以太网驱动
- USB:只留EHCI和USB Host, gadget、OTG都关
- I2C/SPI:只留你实际用的控制器
- 字符设备:tty、串口、rtc、watchdog,其他全关
- 块设备:NAND/MLC驱动留着,其他SATA、SD全部关
第四步:内核调试和开发选项
Kernel hacking里面的东西,发布版基本全关:
- printk如果不需要可以调低级别(或者直接关)
- dynamic debug、ftrace、kprobes全部关
- KGDB、kdump这些调试功能都关
裁剪前后对比
| 项目 | 裁剪前 | 裁剪后 |
|---|---|---|
| zImage大小 | 12.3 MB | 2.8 MB |
| 内核配置项 | ~15000 | ~3500 |
| 启动到shell | ~8s | ~2.1s |
| 运行内存占用 | ~80MB | ~35MB |
一个容易忽略的点:模块 vs 内建
很多人图方便把驱动都编成模块(.ko),但如果你的根文件系统在NAND上,加载模块的时间开销其实不小。对于必须的驱动,直接编进内核(y)比模块(m)启动更快。
我们最终把根文件系统相关的驱动(NAND、UBI、ext4)全部编进内核,其他外设驱动编成模块,按需加载。
大家做嵌入式Linux裁剪的时候,最小做到过多小?有没有什么独门技巧?

