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 核心原则:按需裁剪

  1. 只选系统启动必需的:比如 init、sh、mount、ls、cat、echo、test。这些是系统跑起来的基础。
  2. 调试工具按需添加:比如 ping、telnet、top、ps。开发阶段可以全选,量产阶段只留 ping 和 ps 就够了。
  3. 绝对不选重复功能的:比如 vi 和 nano 都是编辑器,选一个就行。我一般选 vi,因为它更小。
  4. 考虑替代方案:有些功能可以用脚本实现,就不需要编译对应的 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 具体操作步骤

  1. 进入 make menuconfig。
  2. 找到 Settings 菜单。
    • 关闭 Support --long-options。
    • 关闭 Support --verbose。
    • 关闭 Enable locale support。
  3. 找到 Debugging Options。
    • 关闭 Build with debug information。
    • 关闭 Enable runtime debugging。
  4. 逐个检查每个 Applet 的子选项。
    • 比如 ls 里,关闭 Enable color support。
    • 比如 cp 里,关闭 Enable preserve attributes(如果不需要保留文件属性)。

我的经验: 每次裁剪完,都编译一次,然后对比一下体积。用 ls -lh busybox 看看。我一般会记录每次裁剪前后的体积变化,这样心里有数。比如关掉长选项,大概能省 8-12KB;关掉所有彩色输出,能省 5KB 左右。积少成多,最后能省出 100-200KB。

3.4 知识体系:配置裁剪的核心逻辑

说了这么多,你可能有点晕。没关系,我画了一张图,把整个配置裁剪的流程串起来。你一看就明白了。

Busybox 配置裁剪核心流程 Busybox 配置裁剪核心流程 Busybox 源码 make menuconfig 配置界面 选择 Applet 裁剪功能模块 调整编译选项 生成 .config 配置文件 make 编译 核心原则 只选必需的,砍掉多余的

这张图把整个流程串起来了。你从源码出发,进入配置界面,然后同时做三件事:选 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、砍掉多余功能、优化编译选项。每次裁剪完,编译、测试、对比体积。慢慢你就会找到最适合你项目的配置。