2. 裁剪前的准备工作:需求分析、硬件资源评估、软件依赖梳理
系统裁剪这事儿,说白了就是「戴着镣铐跳舞」。你不可能把整个 Linux 发行版塞进一块只有 4MB Flash 的板子里。所以动手之前,必须把三件事搞清楚:你到底要什么、硬件能给你什么、软件之间谁离不开谁。
我见过太多人上来就开干,结果裁到一半发现某个库没编进去,或者 Flash 差了几百 KB。嗯,咱们先把地基打牢。
2.1 需求分析:别让业务部门追着你改
需求分析不是列个功能清单就完事了。你得追问三个层次的问题:
- 业务功能:设备最终要做什么?采集数据?控制电机?还是做人机交互?
- 运行环境:温度范围?供电稳定性?有没有硬实时要求?
- 维护方式:产品生命周期内要不要 OTA 升级?要不要远程调试?
我的经验:有一次做工业网关裁剪,业务方只说「能跑 MQTT 就行」。结果交付后才发现他们还需要本地 Web 配置页面——因为现场工人不会用命令行。这一下多出来 lighttpd + libwebsockets 两个组件,Flash 差点爆了。
所以我的习惯是:让需求方把「必须做」「最好做」「以后可能做」分开列出来。裁剪只保「必须做」,其他的一律砍掉。
2.2 硬件资源评估:你的板子到底有几斤几两
拿到板子后,别急着看 Datasheet 里的理论值。先跑几个命令看看实际可用资源:
# 查看 Flash 分区布局
cat /proc/mtd
# 查看内存使用情况
free -m
# 查看 CPU 信息
cat /proc/cpuinfo
这里有个坑——很多 SoC 的 Flash 和 RAM 是共享总线的。你想想看,如果 Flash 读取占用了太多带宽,CPU 执行代码就会卡顿。我在项目中遇到过一块海思芯片,理论上有 128MB RAM,但实际给应用层可用的只有 80MB 不到,因为 ISP 和硬件编解码模块占掉了剩下的。
硬件评估我一般列个表:
| 资源项 | 理论值 | 实际可用 | 裁剪目标 |
|---|---|---|---|
| Flash 总容量 | 16 MB | 14.2 MB(含坏块) | ≤ 10 MB |
| RAM 总容量 | 64 MB | 52 MB(系统占用) | ≤ 30 MB |
| CPU 主频 | 800 MHz | — | 空闲率 ≥ 30% |
注意:Flash 的实际可用容量一定要考虑坏块和文件系统元数据开销。JFFS2 和 UBIFS 的元数据通常要吃掉 5%~10% 的空间。我曾经因为没算这个,裁完的系统刷进去直接 OOM。
2.3 软件依赖梳理:别让一个库拖垮整个系统
软件依赖是裁剪中最容易翻车的地方。你以为只用了 libc,结果它背后拉着 libpthread、librt、libdl……一层层下去,体积就失控了。
我推荐的做法是:先用工具扫一遍依赖树。
# 查看某个二进制文件的动态库依赖
readelf -d /usr/bin/your_app | grep NEEDED
# 递归查看所有依赖
ldd /usr/bin/your_app
但 ldd 只能看到一级依赖。更狠的办法是用 objdump -p 或者 readelf -d 配合脚本递归解析。我自己写过一个脚本,能把整个依赖树展开成文本,一眼就能看出哪个库是「胖子」。
小技巧:把依赖树输出成 DOT 格式,用 Graphviz 转成图片。视觉上比看文本舒服多了。我每次裁剪前都会生成一张依赖图,贴在工位上。
梳理依赖时,重点关注三类「问题库」:
- 重量级库:比如 libcurl、libxml2、OpenSSL。能换轻量替代就换(如 mbedTLS 代替 OpenSSL)。
- 间接依赖:A 依赖 B,B 依赖 C。你只用了 A,但 C 也被拉进来了。这时候要考虑静态链接或者功能裁剪。
- 调试符号:Release 版本一定要 strip。我见过一个项目,strip 前 5MB,strip 后 1.2MB——差了四倍。
2.4 知识体系总览
下面这张图把裁剪前的准备工作串起来了。你可以把它当作检查清单:
2.5 输出物:裁剪方案文档
以上三步做完,你应该能产出一份裁剪方案文档。我习惯用 Markdown 写,结构大概这样:
# 裁剪方案 v1.0
## 1. 需求清单
- 必须功能:MQTT 上报、GPIO 控制、看门狗
- 可选功能:本地日志、Web 配置(暂缓)
## 2. 硬件资源表
- Flash:16MB → 目标 ≤ 10MB
- RAM:64MB → 目标 ≤ 30MB
- CPU:800MHz → 空闲率 ≥ 30%
## 3. 软件依赖树
- 主程序 → libpthread → libc
- 主程序 → libmosquitto → libc, libssl
- 主程序 → libgpiod → libc
## 4. 裁剪策略
- 替换 OpenSSL → mbedTLS(节省 ~800KB)
- 移除 bash → 改用 busybox ash(节省 ~1.2MB)
- 移除无用驱动模块(节省 ~500KB)
我的习惯:这份文档我会和硬件工程师、业务方一起评审。别自己闷头裁,裁完了发现人家要的功能被你砍了,那才叫尴尬。
准备工作做到位,后面裁剪就是按图索骥。说白了,前面花 80% 的时间把需求、硬件、依赖摸清楚,后面 20% 的时间就能干净利落地把系统裁出来。反过来,前面图省事,后面大概率要返工。