3. 源码获取与结构分析:从官方Git仓库获取源码、目录结构解析、核心文件说明
好,咱们进入正题。这一章我带你干两件事:第一,把BusyBox源码从官方仓库拉下来;第二,把它的目录结构扒开看看,搞清楚每个文件夹是干嘛的。说白了,就是让你拿到源码后不懵圈。
3.1 从官方Git仓库获取源码
我个人习惯用Git直接拉取,这样版本切换方便,想看历史记录也容易。你想想看,万一你裁剪到一半发现某个版本有bug,切个分支就能对比,多省事。
官方仓库地址是:https://git.busybox.net/busybox
拉取命令很简单:
git clone git://git.busybox.net/busybox
cd busybox
嗯,这里要注意,如果你在公司内网或者网络受限,可以用HTTPS方式:
git clone https://git.busybox.net/busybox
拉下来之后,看看有哪些版本:
git tag | head -20
我建议你选一个稳定版本,比如 1_36_1 或者 1_35_0。我在项目中遇到过,用最新开发版有时候会踩坑,比如某个工具突然行为变了,查半天发现是代码还没稳定。所以,生产环境我一般选最近的两个稳定版之一。
git checkout 1_36_1
https://busybox.net/downloads/busybox-1.36.1.tar.bz2。但我还是推荐用Git,方便后续打补丁和回退。
3.2 目录结构解析
拉下来之后,咱们看看顶层目录长什么样。用 ls -la 看一眼:
drwxr-xr-x 2 root root 4096 目录 arch/
drwxr-xr-x 2 root root 4096 目录 applets/
drwxr-xr-x 2 root root 4096 目录 archival/
drwxr-xr-x 2 root root 4096 目录 configs/
drwxr-xr-x 2 root root 4096 目录 console-tools/
drwxr-xr-x 2 root root 4096 目录 coreutils/
drwxr-xr-x 2 root root 4096 目录 debianutils/
drwxr-xr-x 2 root root 4096 目录 docs/
drwxr-xr-x 2 root root 4096 目录 editors/
drwxr-xr-x 2 root root 4096 目录 findutils/
drwxr-xr-x 2 root root 4096 目录 init/
drwxr-xr-x 2 root root 4096 目录 libbb/
drwxr-xr-x 2 root root 4096 目录 libpwdgrp/
drwxr-xr-x 2 root root 4096 目录 loginutils/
drwxr-xr-x 2 root root 4096 目录 mailutils/
drwxr-xr-x 2 root root 4096 目录 miscutils/
drwxr-xr-x 2 root root 4096 目录 modutils/
drwxr-xr-x 2 root root 4096 目录 networking/
drwxr-xr-x 2 root root 4096 目录 printutils/
drwxr-xr-x 2 root root 4096 目录 procps/
drwxr-xr-x 2 root root 4096 目录 runit/
drwxr-xr-x 2 root root 4096 目录 selinux/
drwxr-xr-x 2 root root 4096 目录 shell/
drwxr-xr-x 2 root root 4096 目录 sysklogd/
drwxr-xr-x 2 root root 4096 目录 util-linux/
看着挺多是吧?别慌,我帮你拆开看。这些目录其实分几大类:
| 分类 | 目录名 | 说明 |
|---|---|---|
| 核心框架 | applets/, libbb/ | BusyBox的主框架和公共库函数 |
| 工具集 | coreutils/, util-linux/, networking/ 等 | 各种Linux命令的实现 |
| 配置与构建 | configs/, Makefile, Kbuild | 编译配置和构建系统 |
| 文档与示例 | docs/, examples/ | 使用说明和示例配置 |
| 架构相关 | arch/ | 不同CPU架构的适配代码 |
我重点说说几个关键目录:
- applets/:这是BusyBox的入口。每个工具在这里都有一个对应的
.c文件,比如applets/ls.c。但注意,真正的实现代码并不全在这里,它只是个"壳",负责把命令名映射到实际函数。 - libbb/:这是BusyBox的"公共库"。里面放了很多工具都会用到的函数,比如字符串处理、文件操作、内存分配等。我刚开始看源码时,经常在
libbb/里翻来翻去,因为很多工具都调用了这里的函数。 - coreutils/:核心工具集,像
cat、cp、mv、rm这些最常用的命令都在这里。你裁剪时,这个目录是重点关照对象。 - networking/:网络相关工具,比如
ping、ifconfig、telnet等。如果你的嵌入式设备不需要网络功能,这个目录可以直接砍掉。 - arch/:架构相关代码。比如ARM、MIPS、x86等不同CPU的启动代码和优化。一般不用动,除非你要移植到新平台。
tar 可能依赖 gzip,删之前要检查清楚。
3.3 核心文件说明
除了目录,顶层还有一些关键文件,我挑几个重要的说说:
| 文件名 | 作用 | 我的建议 |
|---|---|---|
| Makefile | 主构建文件,控制整个编译流程 | 一般不动,除非你要改编译选项 |
| Config.in | Kconfig配置文件,定义所有可配置选项 | 裁剪时经常要改,比如去掉某些工具 |
| .config | 编译配置结果文件,由 make menuconfig 生成 |
裁剪的核心文件,你最终要的就是它 |
| applets/Kbuild | 定义哪些applet被编译进BusyBox | 一般通过menuconfig自动生成 |
| include/usage.h | 所有工具的帮助文本定义 | 裁剪时可以删掉不用的帮助文本,节省空间 |
| include/applets.h | 所有applet的声明列表 | 一般不动,但调试时有用 |
我重点说说 .config 文件。这个文件是裁剪的"命根子"。你运行 make menuconfig 后,所有选择都会写到这里。它的格式很简单,比如:
CONFIG_LS=y
CONFIG_CAT=y
CONFIG_GZIP=n
y 表示编译进BusyBox,n 表示不编译。你想想看,如果你不需要 gzip,直接改成 n 就行。但要注意,有些选项是互斥的,比如 CONFIG_FEATURE_xxx 这种特性开关,改错了可能导致编译失败。
.config 文件,把某个依赖关系搞乱了,结果编译报错,查了半天才发现是某个特性开关没开。所以,我建议你尽量用 make menuconfig 来配置,它会自动处理依赖关系。实在要手动改,改完后运行 make oldconfig 检查一下。
还有一个文件值得提一下——include/usage.h。这个文件里存着所有工具的 --help 输出文本。如果你做的是极度精简的系统,可以把不用的工具的帮助文本删掉,能省下几十KB的空间。不过要注意,删的时候要小心,别把还在用的工具的帮助文本也删了。
3.4 知识体系结构图
下面我用一张SVG图,把BusyBox源码的整体结构画出来,方便你理解各个部分的关系:
这张图把BusyBox的源码结构、配置流程、编译输出串起来了。你从左上角开始看:先通过 make menuconfig 生成 .config,然后编译系统根据配置选择对应的工具目录,最后链接成一个 busybox 可执行文件。部署到嵌入式系统后,通过符号链接来调用各个工具。
嗯,这一章的内容就这些。你拿到源码后,先按我说的拉下来,然后进去逛逛,看看每个目录里都有什么。下一章咱们就开始动手裁剪了,到时候我会带你一步步配置,把不需要的工具统统砍掉。
make defconfig 生成默认配置,然后 make 编译一次,确保环境没问题。我第一次编译时,因为缺了 ncurses-dev 库,make menuconfig 报错了。所以,提前装好依赖:sudo apt-get install build-essential ncurses-dev。
可可精品资料库