2. 裁剪前的准备工作:需求分析、硬件资源评估、软件依赖梳理

系统裁剪这事儿,说白了就是「戴着镣铐跳舞」。你不可能把整个 Linux 发行版塞进一块只有 4MB Flash 的板子里。所以动手之前,必须把三件事搞清楚:你到底要什么、硬件能给你什么、软件之间谁离不开谁。

我见过太多人上来就开干,结果裁到一半发现某个库没编进去,或者 Flash 差了几百 KB。嗯,咱们先把地基打牢。

2.1 需求分析:别让业务部门追着你改

需求分析不是列个功能清单就完事了。你得追问三个层次的问题:

  1. 业务功能:设备最终要做什么?采集数据?控制电机?还是做人机交互?
  2. 运行环境:温度范围?供电稳定性?有没有硬实时要求?
  3. 维护方式:产品生命周期内要不要 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 知识体系总览

下面这张图把裁剪前的准备工作串起来了。你可以把它当作检查清单:

裁剪前准备工作流程图 裁剪前准备工作流程 1. 需求分析 2. 硬件资源评估 3. 软件依赖梳理 输出:裁剪方案文档 功能清单 环境约束 维护策略 Flash / RAM 实测 CPU / 总线带宽 ⚠️ 避坑提醒 硬件理论值 ≠ 实际可用值 依赖树一定要递归展开,别只看第一层

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% 的时间就能干净利落地把系统裁出来。反过来,前面图省事,后面大概率要返工。