使用 Busybox 构建微型 Linux 系统——第一部分

作者:Bruce Perens

由于 Linux 体积小且易于定制,因此它是嵌入式系统的理想内核。但是,对于最小化功能性 GNU/Linux 系统所需的所有其他程序呢?Debian 或 Red Hat 安装盘安装的最小系统,不包括内核,大约为 40 兆字节大小。Busybox 用大量命令行工具取代了 GNU/Linux 发行版——启动和运行具有网络的实用 Linux 系统所需的一切——都在一个非常小的软件包中。

Busybox 在 i386 架构上的典型编译大小为所有工具总共 256 到 500K,具体取决于使用的 C 库及其链接方式。这使得创建具有全功能内核、命令行环境以及您的应用程序的单软盘 Linux 系统成为可能。

我最初在 1996 年为 Debian GNU/Linux 安装盘编写了 Busybox。目标是将完整的可引导系统放在单张软盘上,该软盘既可以用作救援盘,又可以用作 Debian 系统的安装程序。救援盘用于在 Linux 系统变得无法启动时修复该系统。因此,救援盘需要能够启动系统并挂载硬盘文件系统,并且它必须提供使硬盘根文件系统恢复到可启动状态所需的命令行工具。在我编写 Busybox 时,Debian 安装程序是一个 Bourne shell 脚本,使用 dialog 在 ANSI 终端或 Linux 控制台上提供简单的图形界面。

自创建以来,许多人为 Busybox 添加和维护了代码,包括 Debian Boot-Floppies 团队、Linux Router Project 和 Lineo Corporation 的成员,Eric Anderson 今天在 Lineo Corporation 维护 Busybox。按照自由软件项目的传统,其他作者的贡献现在构成了该项目的大部分。Busybox 是几乎所有商业嵌入式 Linux 产品的一部分,并且在 Kerbango Internet Radio 和运行 Linux 的 IBM 腕表等各种项目中都可以找到它。

名称 Busybox 来自儿童玩具箱,玩具箱上有一个电话拨号盘和许多旋钮、按钮和其他设备,所有这些设备在操作时都会发出声音。这在过去被称为 busy box,今天通常被称为 activity center(活动中心)。

Busybox 源代码可以在 www.busybox.lineo.com 找到。默认情况下,提供的 Makefile 使用系统上的默认 libc 库构建动态链接可执行文件。但是,它可以轻松地适应交叉编译,并且可以通过编辑 Makefile 变量来选择静态链接和其他专门的 libc 库。在您使用 Makefile 选项或嵌入 Busybox 之前,您应该在主机系统上构建并运行它,以便熟悉它。如果您在安装了开发工具的 Linux 系统上,只需键入 make 即可构建它。

构建 Busybox 后,就该了解 多调用可执行文件 了。这是我们用来缩小 Busybox 体积的技巧。有一个名为 busybox 的可执行文件,它链接到 107 个不同的名称,并提供 107 个不同程序的功能。为了说明这一点,请运行以下 shell 命令

ln busybox ls
ln busybox uptime
ln busybox whoami

现在,运行这些命令

./ls
./uptime
./whoami

请务必键入如上所示的前导“./”,否则您将获得这些命令的系统版本,而不是 Busybox 版本。

ln 命令用于将另一个名称应用于文件。它不会复制文件。它在文件系统中使用的唯一空间是存储目录中的名称所需的小量空间。您可以使用以下 ls 命令来说明这一点

ls -il busybox ls uptime whoami

请务必如上所述对 ls 使用 -il 参数。这会导致 ls 打印 inode 号,inode 号是标识文件系统中每个文件的唯一编号,以及 -l 参数提供的常用长列表。Linux 允许同一个文件有多个名称,但一个文件只有一个 inode 号。您应该看到类似于列表 1 的内容。

1849054 -rwxrwxr-x      4       bruce   bruce   252956  Sep     7       08:22   busybox
1849054 -rwxrwxr-x      4       bruce   bruce   252956  Sep     7       08:22   ls
1849054 -rwxrwxr-x      4       bruce   bruce   252956  Sep     7       08:22   uptime
1849054 -rwxrwxr-x      4       bruce   bruce   252956  Sep     7       08:22   whoami

请注意,这不是四个文件的列表。它是具有四个名称的一个文件的列表,如第一列中的 inode 号和第三列中的 链接计数 所示。链接计数报告文件有多少个名称。您会注意到,常见 Linux 文件系统中的目录始终具有为 2 的链接计数,因为它们有两个名称:“.”和“..”。但是,大多数文件只有一个名称,其链接计数为 1。

由于每个可执行程序都有几千字节的固定开销,因此将 107 个命令压缩到一个文件中可以节省大量空间。因此,正如我们将 Busybox 链接到四个不同的名称一样,我们可以将其链接到 107 个名称。这为我们提供了一个完整的、可启动的、可运行的 Linux 系统,占用空间非常小。即使使用已成为 Linux 系统标准的 GNU LIBC 6 进行静态链接,Busybox 也仅占用半兆字节。

如果您不需要 LIBC 6 的国际化功能,则旧的 LIBC 5 会小得多。一个新的专为嵌入式使用而设计的库 uC-Libc (www.opensource.lineo.com) 甚至更小,但如果您的应用程序是专有的,请谨慎使用。与 Busybox 一样,uC-Libc 受 GNU GPL(通用公共许可证)保护,不能链接到专有软件。相比之下,GNU LIBC 5 和 6 在 LGPL(较宽松通用公共许可证)下,可以链接到专有应用程序。因此,不要将 uC-Libc 用于非自由程序的 libc 库。在撰写本文时,uC-Libc 尚未完全提供 Busybox 所需的所有功能,但仅缺少一些功能,并且在您阅读本文时可能会提供这些功能。

表 1. 提供的工具

在 Debian 安装软盘上,我动态链接了 Busybox,然后剥离了共享的 libc 库,使其仅提供支持 Busybox 和软盘上其他可执行文件所需的功能。这是提供由几个不同可执行文件共享的库的最佳方法,因为软盘除了 Busybox 之外还包含其他程序。将 libc 剥离到仅实际使用的功能使其大小减少了一半。我没有手动剥离它,而是编写了一个脚本,该脚本查找一组动态可执行文件引用的所有库函数,然后创建一个提供这些函数(以及它们所依赖的函数)的库子集。此脚本此后已完全被 Marcus Brinkmann 编写的版本取代,该版本可以在 Debian boot-floppies 包的 scripts/rootdisk/mklibs.sh 下找到。脚本及其工作原理是另一篇文章的主题,其大小与本文相当,但是,在该文章编写完成之前,可以通过在 Debian 系统上安装 boot-floppies 包、构建软盘,然后仔细阅读脚本来弄清楚 mklibs.sh 的工作原理。警告:mklibs.sh 可能是您将要检查的最复杂的 shell 脚本。

那么,既然您知道如何构建和运行 Busybox,那么如何制作一个包含它的微型 Linux 系统呢?您需要几个部分:一个静态链接的 Busybox 可执行文件、一个骨架根文件系统和填充了适当特殊文件的 /dev 目录,以及一个具有您所需功能的 Linux 内核,外加两个将用于启动和运行微型 Linux 系统的功能:RAM 磁盘和压缩 ROM 文件系统。[有关如何构建包含 Busybox 的微型 Linux 系统的详细信息,请参阅未来版本——编辑。]

电子邮件:bruce@perens.com

加载 Disqus 评论