3、配置裁剪入门:make menuconfig详解、选择Applet的原则、去掉不需要的功能模块。
好,咱们进入正题。上一章我们把 Busybox 编译出来了,但那个二进制文件说实话,挺胖的。你想想看,一个嵌入式设备 Flash 可能就 4MB、8MB,你一个 busybox 占掉 1MB,别的还放不放?
所以这一章,咱们就聊聊怎么给它「减肥」。核心就三个事:怎么用配置界面、怎么挑 Applet、怎么砍掉没用的功能。说白了,就是让你手里的刀更锋利。
3.1 make menuconfig 界面详解
我个人习惯,拿到一个 Busybox 源码包,第一件事就是跑 make menuconfig。别急着编译,先看看它到底能干什么。
核心命令:
make menuconfig
这个命令会打开一个基于 ncurses 的图形化配置界面。如果你在服务器上 SSH 连过去,只要终端支持,就能用。
界面长什么样?顶部是菜单栏,中间是配置树,底部是操作提示。我刚开始用的时候,觉得这玩意儿挺复古的,但用久了你会发现,它比那些花里胡哨的 Web 配置界面高效得多。
3.1.1 界面布局
- 菜单栏:
Arrow keys导航,Enter进入子菜单,Space切换选中状态。 - 配置项前缀:
[ ]—— 复选框,按Y编译进内核(或 Busybox),按N排除。< >—— 三态选择,可以编译进内核、编译成模块(对 Busybox 不适用)、或者不编译。--->—— 子菜单,按Enter进入。
- 底部快捷键:
按键 功能 Y选中(编译进 Busybox) N排除(不编译) M模块化(Busybox 里基本用不到) ?查看帮助 /搜索配置项 Z重置当前项为默认值
小技巧: 按 / 键可以搜索。比如你想找 vi 编辑器,直接输入 vi,它会列出所有包含 vi 的配置项。我在项目中经常用这个功能,比一层层翻菜单快多了。
3.1.2 配置项分类
Busybox 的配置项大致分这么几类:
- Applet 选择:每个 Applet 对应一个 Linux 命令。比如
ls、cp、cat。 - 功能特性:比如是否支持长选项(
--help)、是否支持彩色输出。 - 编译选项:比如优化级别、调试符号、静态链接。
- 安装路径:编译后的二进制文件安装到哪个目录。
3.2 选择 Applet 的原则
Applet 是 Busybox 的灵魂。每个 Applet 就是一个命令。但问题来了:是不是所有命令都要编译进去?
当然不是。我见过有人把 Busybox 所有 Applet 全选上,编译出来 1.5MB,放到只有 2MB Flash 的路由器上,结果连个 Web 界面都放不下。这就是典型的「贪多嚼不烂」。
3.2.1 核心原则:按需裁剪
- 只选系统启动必需的:比如
init、sh、mount、ls、cat、echo、test。这些是系统跑起来的基础。 - 调试工具按需添加:比如
ping、telnet、top、ps。开发阶段可以全选,量产阶段只留ping和ps就够了。 - 绝对不选重复功能的:比如
vi和nano都是编辑器,选一个就行。我一般选vi,因为它更小。 - 考虑替代方案:有些功能可以用脚本实现,就不需要编译对应的 Applet。比如
watch命令,可以用while true; do ...; sleep 1; done替代。
我曾经踩过的坑: 有一次我把 login 和 getty 都去掉了,结果系统启动后直接进不了 shell。后来才发现,init 需要 getty 来打开终端。所以,启动链上的 Applet 一个都不能少。
3.2.2 如何判断一个 Applet 是否必要?
我有个习惯:先编译一个全功能的 Busybox,然后放到目标系统上跑一遍。用 strace 或者 busybox --list 看看哪些命令被调用了。没被调用的,统统砍掉。
快速查看已编译 Applet 列表:
# 在目标系统上执行
busybox --list
# 或者查看编译后的二进制文件
./busybox --list-full
3.3 去掉不需要的功能模块
选完 Applet,还没完。每个 Applet 本身还有很多功能开关。比如 ls 命令,支持 -l、-a、-R、--color 等等。这些功能都是代码,都是体积。
3.3.1 常见可裁剪的功能模块
| 功能模块 | 说明 | 裁剪建议 |
|---|---|---|
| 长选项支持 | 如 --help、--version | 量产环境可以去掉,节省约 10KB |
| 彩色输出 | 如 ls --color | 嵌入式终端一般不支持彩色,去掉 |
| 国际化/本地化 | 多语言支持 | 嵌入式系统只用英文,去掉 |
| 调试符号 | -g 编译选项 | 发布版本必须去掉,能省 30%-50% 体积 |
| 静态链接 | 把库函数编译进二进制 | 如果目标系统有 uClibc 或 musl,可以动态链接,体积更小 |
| 未使用的 Applet | 如 arp、route 等网络工具 | 如果系统不用网络,全部去掉 |
3.3.2 具体操作步骤
- 进入
make menuconfig。 - 找到
Settings菜单。- 关闭
Support --long-options。 - 关闭
Support --verbose。 - 关闭
Enable locale support。
- 关闭
- 找到
Debugging Options。- 关闭
Build with debug information。 - 关闭
Enable runtime debugging。
- 关闭
- 逐个检查每个 Applet 的子选项。
- 比如
ls里,关闭Enable color support。 - 比如
cp里,关闭Enable preserve attributes(如果不需要保留文件属性)。
- 比如
我的经验: 每次裁剪完,都编译一次,然后对比一下体积。用 ls -lh busybox 看看。我一般会记录每次裁剪前后的体积变化,这样心里有数。比如关掉长选项,大概能省 8-12KB;关掉所有彩色输出,能省 5KB 左右。积少成多,最后能省出 100-200KB。
3.4 知识体系:配置裁剪的核心逻辑
说了这么多,你可能有点晕。没关系,我画了一张图,把整个配置裁剪的流程串起来。你一看就明白了。
这张图把整个流程串起来了。你从源码出发,进入配置界面,然后同时做三件事:选 Applet、裁功能、调选项。最后生成配置文件,编译。就这么简单。
3.5 实战:一个最小系统的配置示例
光说不练假把式。我给你一个实际项目的配置清单。这是一个基于 ARM Cortex-M4 的 IoT 网关,Flash 只有 4MB,RAM 256KB。
最小系统 Applet 清单:
# 必须保留
CONFIG_INIT=y
CONFIG_SH=y
CONFIG_MOUNT=y
CONFIG_UMOUNT=y
CONFIG_LS=y
CONFIG_CAT=y
CONFIG_ECHO=y
CONFIG_TEST=y
CONFIG_TRUE=y
CONFIG_FALSE=y
# 调试用(量产可去掉)
CONFIG_PING=y
CONFIG_PS=y
CONFIG_TOP=y
CONFIG_FREE=y
# 网络功能(如果不需要网络,全部去掉)
# CONFIG_IFCONFIG is not set
# CONFIG_ROUTE is not set
# CONFIG_ARP is not set
# 编辑器(选一个最小的)
CONFIG_VI=y
# CONFIG_NANO is not set
# 文件系统工具
CONFIG_CP=y
CONFIG_MV=y
CONFIG_RM=y
CONFIG_MKDIR=y
CONFIG_RMDIR=y
CONFIG_TOUCH=y
这个配置编译出来,Busybox 二进制大约 280KB。放到 4MB Flash 里,还剩 3.7MB 给应用程序和文件系统。够用了吧?
注意: 这个清单只是示例。你的项目可能需要 telnetd、httpd 或者 crond。别照搬,要根据实际需求来。我见过有人直接复制网上的配置,结果系统启动不了,因为少了 init 或者 sh。嗯,这种坑我年轻时也踩过。
3.6 本章小结
配置裁剪,说白了就是「做减法」。你不需要把所有功能都塞进去,只需要让系统能跑起来、能满足业务需求就行。记住三个原则:按需选择 Applet、砍掉多余功能、优化编译选项。每次裁剪完,编译、测试、对比体积。慢慢你就会找到最适合你项目的配置。