使用 BusyBox 构建微型 Linux 系统,第 3 部分

作者:Bruce Perens

这是“使用 BusyBox 构建微型 Linux 系统”系列文章的第三篇。如果您手头没有上一期的纸质副本,您需要参考我在 2001 年 1/2 月刊 ELJ 上关于内核构建的上一篇文章(第 2 部分),您可以在在线杂志存档中找到:http://embedded.linuxjournal.com/magazine/issue01/4395/ [第 1 部分发表在 ELJ 增刊(2000 年 11 月)中,可在 http://embedded.linuxjournal.com/magazine/issue00/4335/ 获取。]

在本文中,我们将为您的微型 Linux 系统添加可写存储和多用户功能,当我们完成时,系统将比我们开始时小得多。

时光飞逝

自从我写了前两篇文章以来,BusyBox 及其相关程序的进展一直在继续,这主要归功于 Erik Andersen 的努力,我在第一篇文章中错误地拼写了他的名字。Erik 在 BusyBox 和相关程序方面的工作得到了 Lineo 的支持,并使整个嵌入式 Linux 社区受益。Erik 和他的同事们继续使用我选择的原始许可证 GPL 为 BusyBox 做出贡献,并且他们为 GPL 和 LGPL 下的其他嵌入式程序做出了巨大贡献。

在我的上一篇文章中,由于 2.4 版本中的一个错误,我们使用了 2.2 内核。现在该错误已被修复,并且由于 2.4 内核已发布,让我们尝试一下。syslinux 也已更新以适应新内核。

要下载的软件

我们将使用一些新软件:TinyLogin 和 uClibc,以及新版本的 BusyBox 和 syslinux。创建一个您将在此示例中工作的目录,并切换到该目录。从 https://linuxkernel.org.cn 或其任何镜像下载 2.4 内核源代码。从 ftp://ftp.perens.com/ELJ/3/ 下载所有文件。阅读 README.txt 文件。解压缩您刚刚下载的压缩 tar 存档。暂时不要运行 shell 脚本 as_in_episode_2.sh。从下载的源代码构建并安装 syslinux,如果您已在系统上安装了旧版本,请替换旧版本。从下载的源代码构建 BusyBox。

熟悉 2.4 内核

花时间在 BusyBox 软盘上安装 2.4 内核,只是为了熟悉配置和运行它。我们将使用 elj-3 目录中的一些脚本来省去您在内核文章中做的大部分打字工作。

如果您仍然有我们在第二篇文章中使用的 tiny Linux 目录,请将其移开。我们即将创建一个新的。

解压内核源代码并按照我们在上一篇文章的子标题“构建内核”下配置内核的方式配置它,但如果内核中尚未包含 DOS FAT 文件系统和 VFAT (Windows 95) 文件系统,请向内核添加这两个新功能。这些功能位于内核配置的文件系统菜单中。您需要在您的开发系统和您的微型 Linux 系统上使用这些文件系统,因此您最终可能会构建和安装两个内核。请记住,您需要保持您的微型 Linux 系统上的内核足够小,因此它可能与您在开发系统上运行的内核不同。

转到 BusyBox 源代码目录并编辑 Makefile,将 DOSTATIC 设置为 true 以构建 BusyBox 的静态链接版本。使用 make 命令构建 BusyBox,然后运行

make PREFIX=../tiny-linux install-hardlinks

这将在 BusyBox 目录上方的目录中创建 tiny Linux 目录,并在 tiny Linux 目录中创建 bin、sbin 和 /usr/sbin 目录。Makefile 将在目录树中安装 BusyBox,并将为各种命令名称创建所有链接,自动完成我们在第 2 部分中手动执行的大部分工作。它不会安装脚本和文件,也不会创建 /dev 目录。您下载的脚本之一将执行此操作。将目录更改为 ../elj-3 并运行

sh -x as_in_episode_2.sh ../tiny-linux
这将创建 /dev 和 /etc 目录的内容以及制作 ROM 文件系统所需的任何其他内容。

现在,按照我在 2001 年 1/2 月刊文章中“生成 ROM 根文件系统映像”和“构建软盘”子标题下的说明进行操作。最后,启动软盘进行测试。

让我们缩小尺寸

Erik 和其他人一直在做的另一件好事是 uClibc,免费的嵌入式 C 库。我之前曾错误地认为该库是在 GPL 许可证下,但实际上 uClibc 是在 LGPL 下,因此可以与专有应用程序链接。现在,您可以使 BusyBox 静态链接以与 uClibc 而不是 libc5 或 libc6 一起运行。结果小于 300K,当然,当 ROM 文件系统被压缩时,它会变得更小。在 uClibc 源代码目录中,编辑配置文件并将 HAS_MMU 更改为 true,将 HAS_FLOATS 更改为 true,并将 KERNEL_SOURCE 更改为您的内核源代码的位置。将 CC 的定义更改为 $(CROSS)gcc -Os 以优化更小的代码大小。如果您的 gcc 版本不支持 -Os 标志,请改用 -O2。运行 make 以构建 libc.a 库。在本文中,uClib 仅支持静态链接,但动态链接刚刚开始工作。我们将给它一点时间来稳定,并在下一期中介绍它。

现在,回到 BusyBox 源代码,编辑 Makefile 并查找如下所示的行:“要针对备用 libc 进行编译,您可能需要使用/调整以下源代码行以满足您的需求”。在该部分下方是定义 LIBCDIR、LDFLAGS、LIBRARIES、CROSS_CFLAGS 和 GCCINCDIR 的行。大多数或所有这些定义都被注释掉了。取消注释这些定义以启用与 uClibc 的链接。将 LIBCDIR 的定义更改为您的 uClibc 源代码的位置。编辑 Config.h,并注释掉 BB_GETOPT 和 BB_FEATURE_NFSMOUNT 定义,以禁用 getopt 命令以及使用 mount 命令挂载远程 NFS 文件系统的能力。在我撰写本文时,有一个错误阻止 BusyBox getopt 命令与 uClibc 一起工作,但当您阅读本文时,该错误可能已修复。uClibc 目前不包含网络支持,尽管我相信最终会有人添加它。

现在,使用 make clean 和 make 命令重建所有 BusyBox。在我的系统上,结果是一个大小为 297,620 字节的静态链接可执行文件。

删除文件 tiny-linux/bin/getopt。这次不会生成该文件,因为我们关闭了 BB_GETOPT 的定义。如果我们不删除它,我们将最终得到两个版本的 BusyBox 和大量浪费的空间。

使用上面“熟悉 2.4 内核”下的说明,从命令开始

make PREFIX=../tiny-linux install-hardlinks

这将生成另一个软盘。启动软盘进行测试。

添加可写存储

到目前为止,您的微型 Linux 系统中可能最大的缺失功能是缺少可写存储。让我们现在修复它。我们将使用 VFAT 文件系统作为可写存储。这是旧的 DOS FAT 文件系统的扩展,用于处理长文件名和混合大小写文件名,为 Windows 95 引入的。由于您的软盘已经使用 DOS 文件系统来保存内核和压缩的 ROM 映像文件,因此最容易使用 VFAT 来扩展该文件系统以用于此示例。成为 root 用户。创建一个 tiny var 目录。此目录树将保存将在您的微型 Linux 系统上可写的文件。稍后您将复制到软盘,并在您的微型 Linux 系统启动时将其挂载到 /floppy/var。

使用命令将您的整个 tiny-linux/etc 目录移动到 tiny-var/etc

mv tiny-linux/etc tiny-var

创建另外两个目录:tiny-var/shm 和 tiny-var/home。第一个目录由 mount 命令用作提供共享内存时的占位符,第二个目录用于保存用户的 home 目录。

现在我们将在 tiny Linux 中创建符号链接,将一些目录重定向到 /var,以便您可以访问您的可写存储,然后将 /var 重定向到 /floppy/var。我们在这里分两级进行符号链接,以便可以通过仅替换一个链接来更改所有可写存储的位置

cd tiny-linux
rm -f -r var
mkdir floppy
ln -s floppy/var var
ln -s var/etc etc
ln -s var/home home

创建如下所示的 shell 脚本 startup.sh

#! /bin/sh
/bin/mount -t vfat /dev/fd0 /floppy
exec /sbin/init
此脚本将在系统启动时运行,而不是 init,因为我们将为内核提供一个特殊的命令行参数。它将挂载软盘,以便在 init 启动之前 /etc 的内容是正确的。请注意,exec /sbin/init 与简单地运行 /sbin/init 不同。exec 命令表示用给定的程序替换 shell,而不是将程序作为 shell 的子进程运行。因此,init 将在与 shell 相同的进程 ID 中运行,在这种情况下,进程 ID 将为 1。这很重要,因为内核为进程 ID 1 提供了一些特殊属性,并且除非 init 在进程 ID 1 中,否则它将无法正常运行。

更改脚本的模式,使其可执行

chmod 744 startup.sh

向上更改目录一级 (cd ..)

使用编辑器修改文件 tiny-var/etc/inittab,该文件告诉 /bin/init,系统启动程序,要启动哪些进程。文件的全部内容应如下所示

::sysinit:/etc/init.d/rcS
::askfirst:/bin/sh
::ctrlaltdel:/sbin/swapoff -a
::ctrlaltdel:/bin/umount -a

我们在此处添加行以在关机时干净地卸载文件系统,以便卸载包含可写文件的软盘文件系统。以 ::ctrlaltdel: 开头的行上的任务将在系统停止之前执行。我们还会关闭任何已激活的交换分区,以防它们位于已挂载的文件系统上。

创建挂载软盘所需的特殊设备文件

mknod tiny-linux/dev/fd0 b 2 0
chmod 644 tiny-linux/dev/fd0

现在,从 tiny Linux 目录重新生成 ROM 文件系统,像以前一样使用 genromfs,并使用 gzip 压缩它以创建一个新的 fs.gz。

使用此命令挂载您的软盘

mount -t vfat /dev/fd0 /mnt

并将新的 fs.gz 复制到您的 tiny Linux 软盘,替换旧的 ROM 文件系统。

使用命令将 tiny var 目录树复制到您的软盘

mkdir /mnt/var
cp -R tiny-var/* /mnt/var

通过编辑文件 /mnt/syslinux.cfg,告诉内核运行 /startup.sh 而不是 /sbin/init。更改如下所示的行

APPEND root=/dev/ram0 initrd=fs.gz
改为
APPEND root=/dev/ram0 initrd=fs.gz init=startup.sh
将目录更改为 /,并使用此命令卸载软盘
umount /dev/fd0
您现在应该能够启动软盘,并且目录 /var、/etc 和 /home 应该是可写的。
单软盘上的多用户系统

您的微型 Linux 系统目前仅以 root 用户身份登录。让我们创建一个更通用的系统,该系统支持用户和组名、登录命令、通过控制台、调制解调器或串行线路登录的支持以及添加和删除用户的实用程序。让我们也使磁盘可写,这与我们在第二篇文章中制作的系统不同。让我们将所有这些以及我们包含 100 多个通用 UNIX 命令的 BusyBox 工具包都安装在一张软盘上,并且还有剩余空间!

进入 TinyLogin 源代码目录并编辑 Makefile。我们将使用 uClibc 构建 TinyLogin,因此将 DOSTATIC 设置为 true,注释掉 LIBRARIES 定义中的 -lcrypt,并将 USE_SYSTEM_PWD_GRP 设置为 true。在 Makefile 中查找如下所示的行:“要针对备用 libc 进行编译,您可能需要使用/调整以下行以满足您的需求。” 以与您更改 BusyBox Makefile 以启用使用 uClibc 构建相同的方式更改下方的行。

警告:如果您曾经将 TinyLogin 与使用名称服务交换 (NSS) 的 C 库链接,包括 GNU LIBC 以及您开发系统上的默认 libc,则必须在 Makefile 中将 USE_SYSTEM_PWD_GRP 设置为 false。这将替换读取 /etc/passwd 和 /etc/group 文件等的函数,替换为不使用 NSS 的版本。我们的微型 Linux 系统不提供 NSS 工作所需的文件和其他设施,因此 TinyLogin 在使用它构建时会失败。这是 TinyLogin 最常报告的“错误”,其作者非常厌倦向每个报告此“错误”的人解释 NSS 的工作原理。

使用 make 命令构建 TinyLogin。结果应该约为 58K 大小。

使用以下命令在您的 tiny Linux 目录中安装 TinyLogin

make PREFIX=../tiny-linux install-hardlinks

向上更改目录一级 (cd ..)。

使用编辑器修改文件 tiny-var/etc/inittab,该文件告诉 /bin/init,系统启动程序,要启动哪些进程。文件的全部内容应如下所示

::sysinit:/etc/init.d/rcS
tty1::askfirst:/bin/login
tty2::askfirst:/bin/login
tty3::askfirst:/bin/login
tty4::askfirst:/bin/login
::respawn:/sbin/getty -L ttyS0 9600
::respawn:/sbin/getty -L ttyS1 9600
::ctrlaltdel:/sbin/swapoff -a
::ctrlaltdel:/sbin/umount -a

这将系统配置为在前四个控制台虚拟终端和前两个串行端口上以 9,600 波特率提供登录。创建包含以下行的文件 tiny-var/etc/passwd

root::0:0:Super User:/:/bin/sh
创建包含以下行的 tiny-var/etc/group
root:x:0:
创建终端设备
cd tiny-linux/dev
mknod tty0 c 4 0
mknod tty1 c 4 1
mknod tty2 c 4 2
mknod tty3 c 4 3
mknod tty4 c 4 4
mknod ttyS0 c 4 64
mknod ttyS1 c 4 65
chmod 600 tty0 tty1 tty2 tty3 tty4 ttyS0 ttyS1
向上更改目录两级 (cd ../..)。

重新生成压缩的 ROM 文件系统,并像以前一样将其安装在软盘上。使用此命令将新的 tiny var 复制到软盘

cp -R tiny-var/* /mnt/var

卸载软盘。启动软盘进行测试。当软盘启动时,您将获得登录提示。使用 root 作为您的登录名——目前没有密码(但即将有)。您会看到一些关于缺少文件的抱怨。现在,您可以尝试使用 adduser 和 passwd 命令。您应该能够添加用户并设置他们的密码。添加一些用户后,您可以登录他们。要访问其他控制台虚拟终端之一,请键入 Ctrl+Alt+F2 到 Ctrl+Alt+F4。Ctrl+Alt+F1 将使您返回到第一个虚拟控制台。您应该能够为每个虚拟终端登录不同的用户。如果可以,请将两个串行终端设置为 9,600 波特率,连接到系统的前两个串行端口。您也应该能够在每个终端上都有用户。

随意添加缺少的文件并测试 TinyLogin 包中的其他程序。要拥有功能齐全的系统,您需要 /etc/shadow、/etc/gshadow、/etc/securetty 和 utmp 文件。utmp 文件的位置在您的开发系统上的 /usr/include/paths.h 中定义。

安全性将不存在,因为 VFAT 文件系统不支持提供安全性所需的所有权和模式信息。如果您实际上需要此系统是安全的,则必须将 VFAT 替换为另一个文件系统。USMSDOS 文件系统是 VFAT 的良好替代品。其他文件系统只是稍微复杂一些,因为它们与 syslinux 用于加载内核和 ROM 文件系统映像的 MS-DOS FAT 文件系统不兼容。您可以将 FAT 文件系统完全替换为 MINIX 或 EXT2 文件系统,但您必须将引导加载程序从 syslinux 切换到 LILO 或 grub。您还可以从另一个磁盘驱动器挂载可写文件系统。

接下来

在下一期中,我们将研究安全性,并将提供 TinyLogin 使用的剩余功能。不要让这阻止您在此期间进行实验——如果您自己弄清楚,您将更好地理解系统的工作原理。我们将添加动态链接和共享库以及其他一些令人兴奋的新功能。所以,请继续关注!

Building Tiny Linux Systems with BusyBox, Part 3

Bruce Perens (bruce@perens.com) 是 Linux Capital Group 的总裁,Progeny Linux Systems 和 Known Safe 的董事长。他曾担任 Debian 项目的项目负责人两年半。

电子邮件:bruce@perens.com

加载 Disqus 评论