创建根文件系统涉及到选择系统运行所需的文件。在本节中,我们将描述如何构建压缩根文件系统。一个不太常见的选择是在软盘上构建一个未压缩的文件系统,该文件系统直接挂载为根目录;这种替代方案在第 9.1 节中描述。
根文件系统必须包含支持完整 Linux 系统所需的一切内容。为了做到这一点,磁盘必须包含 Linux 系统的最低要求
基本文件系统结构,
最低目录集/dev, /proc, /bin, /etc, /lib, /usr, /tmp,
基本实用程序集sh, ls, cp, mv,等等,
最低配置文件集rc, inittab, fstab,等等,
设备/dev/hd*, /dev/tty*, /dev/fd0,等等,
运行时库,用于提供实用程序使用的基本功能。
当然,只有当您可以在其上运行某些程序时,任何系统才变得有用,而根磁盘通常只有在您可以执行以下操作时才变得有用,例如
检查另一个驱动器上的文件系统,例如,要检查硬盘上的根文件系统,您需要能够从另一个驱动器启动 Linux,就像使用根磁盘系统一样。然后,您可以在原始根驱动器未挂载时在其上运行 fsck。
使用归档和压缩实用程序(例如)从备份中还原原始根驱动器的全部或部分cpio, tar, gzip和ftape.
我们描述如何构建压缩文件系统,之所以称为压缩文件系统,是因为它在磁盘上被压缩,并且在启动时被解压缩到 ramdisk 上。使用压缩文件系统,您可以将许多文件(大约六兆字节)放入标准的 1440K 软盘中。因为文件系统比软盘大得多,所以它不能在软盘上构建。我们必须在其他地方构建它,压缩它,然后将其复制到软盘。
为了构建这样的根文件系统,您需要一个备用设备,该设备足够大,可以在压缩之前容纳所有文件。您将需要一个能够容纳大约四兆字节的设备。有几种选择
使用 ramdisk (DEVICE =/dev/ram0)。在这种情况下,内存用于模拟磁盘驱动器。ramdisk 必须足够大,以容纳适当大小的文件系统。如果您使用 LILO,请检查您的配置文件(/etc/lilo.conf)中类似这样的行RAMDISK = nnn这确定了可以分配给 ramdisk 的最大 RAM。默认值为 4096K,这应该足够了。您可能不应该尝试在 RAM 小于 8MB 的机器上使用这样的 ramdisk。检查以确保您有类似这样的设备/dev/ram0, /dev/ram或/dev/ramdisk。如果没有,请使用 mknod 创建(主设备号 1,次设备号 0)。/dev/ram0使用 mknod 创建(主设备号 1,次设备号 0)。
如果您有足够大的(几兆字节)未使用硬盘分区,这是可以接受的。
使用环回设备,它允许将磁盘文件视为设备。使用环回设备,您可以在硬盘上创建一个三兆字节的文件,并在其上构建文件系统。
输入 man losetup 以获取有关使用环回设备的说明。如果您没有 losetup,您可以从以下位置获取它以及兼容版本的 mount 和 unmountutil-linux软件包,位于目录 ftp://ftp.win.tue.nl/pub/linux/utils/util-linux/。
如果您没有环回设备(/dev/loop0, /dev/loop1等)在您的系统上,您将必须使用 ``mknod /dev/loop0 b 7 0'' 创建一个。一旦您安装了这些特殊的 mount 和 umount 二进制文件,请在硬盘上创建一个具有足够容量的临时文件(例如,/tmp/fsfile)。您可以使用类似这样的命令
dd if=/dev/zero of=/tmp/fsfile bs=1k count=nnn |
在下面使用文件名代替 DEVICE。当您发出 mount 命令时,您必须包含选项-o loop告诉 mount 使用环回设备。
在您选择了这些选项之一后,使用以下命令准备 DEVICE
dd if=/dev/zero of=DEVICE bs=1k count=4096 |
此命令将设备清零。
![]() | 将设备清零至关重要,因为文件系统稍后将被压缩,因此所有未使用的部分都应填充零以实现最大压缩。在文件系统上移动或删除文件时,请记住这一点。文件系统将正确地取消分配块,但不会再次将其清零。如果您执行大量删除和复制操作,则压缩后的文件系统最终可能会比必要的要大得多。 |
接下来,创建文件系统。Linux 内核识别两种文件系统类型,用于自动复制到 ramdisk 的根磁盘。这些是 minix 和 ext2,其中 ext2 是首选。如果使用 ext2,您可能会发现使用以下选项很有用-N选项来指定比默认值更多的 inodes;-N 2000建议这样做,这样您就不会耗尽 inodes。或者,您可以通过删除大量不必要的/dev文件来节省 inodes。mke2fs 默认情况下将在 1.44Mb 软盘上创建 360 个 inodes。我发现 120 个 inodes 在我当前的救援根磁盘上足够了,但是如果您包含所有设备在/dev中,您将很容易超过 360 个。使用压缩根文件系统允许更大的文件系统,因此默认情况下有更多的 inodes,但您可能仍然需要减少文件数量或增加 inodes 数量。
因此您使用的命令将如下所示
mke2fs -m 0 -N 2000 DEVICE |
(如果您使用的是环回设备,则应使用您使用的磁盘文件代替此 DEVICE。)
mke2fs 命令将自动检测可用空间并相应地配置自身。``-m 0'' 参数阻止它为 root 保留空间,从而在磁盘上提供更多可用空间。
接下来,挂载设备
mount -t ext2 DEVICE /mnt |
这是您的根文件系统的合理最低目录集 [1]
/dev-- 设备文件,执行 I/O 所必需的
/proc-- proc 文件系统所需的目录存根
/etc-- 系统配置文件
/sbin-- 关键系统二进制文件
/bin-- 被认为是系统一部分的基本二进制文件
/lib-- 提供运行时支持的共享库
/mnt-- 用于维护其他磁盘的挂载点
/usr-- 其他实用程序和应用程序
这些目录中的三个在根文件系统上将为空,因此它们只需要使用 mkdir 创建即可。/proc目录基本上是放置 proc 文件系统的存根。目录/mnt和/usr仅是在启动/根系统运行后使用的挂载点。因此,这些目录也只需要创建。
剩余的四个目录在以下各节中描述。
一个/dev目录,其中包含系统中所有要使用的设备的特殊文件,对于任何 Linux 系统都是强制性的。目录本身是一个普通目录,可以使用以下命令创建mkdir以正常方式。但是,设备特殊文件必须以特殊方式创建,使用 mknod 命令。
不过,有一个快捷方式——从您现有的硬盘复制设备文件/dev目录。唯一的要求是您使用以下命令复制设备特殊文件-R选项。这将复制目录,而不会尝试复制文件的内容。务必使用*大写 R*。例如
cp -dpR /dev/fd[01]* /mnt/dev cp -dpR /dev/tty[0-6] /mnt/dev |
如果您想以更困难的方式进行,请使用ls -l以显示您想要的设备的主设备号和次设备号,并使用以下命令在软盘上创建它们mknod.
无论设备文件是如何创建的,请检查您需要的任何特殊设备是否已放置在救援软盘上。例如,ftape使用磁带设备,因此如果您打算从启动盘访问软盘磁带驱动器,则需要复制所有这些设备。
请注意,每个设备特殊文件都需要一个 inode,并且 inodes 有时可能是一种稀缺资源,尤其是在软盘文件系统上。您需要有选择地选择您包含的设备文件。例如,如果您没有 SCSI 磁盘,您可以安全地忽略/dev/sd*;如果您不打算使用串口,您可以忽略/dev/ttyS*.
如果在构建根文件系统时,您收到错误设备上没有剩余空间但是一个df命令显示仍有可用空间,您可能已经耗尽了 inodes。一个df -i将显示 inode 使用情况。
![]() | 务必包含此目录中的以下文件console, kmem, mem, null, ram0和tty1. |
/etc 目录包含配置文件。它应该包含什么取决于您打算运行的程序。在大多数系统中,这些可以分为三组
始终需要,例如rc, fstab, passwd.
可能需要,但没有人能确定。
偷偷溜进来的垃圾。
ls -ltru |
在我的根软盘上,我将配置文件数量减少到 15 个。这减少了我的工作量,只需处理三组文件
我必须为启动/根系统配置的文件
rc.d/*-- 系统启动和运行级别更改脚本
fstab-- 要挂载的文件系统列表
inittab-- init 进程的参数,这是启动时启动的第一个进程。
gettydefs-- init 进程的参数,这是启动时启动的第一个进程。
我应该为启动/根系统整理的文件
passwd-- 用户、主目录等的关键列表。
group-- 用户组。
shadow-- 用户密码。您可能没有这个。
termcap-- 终端能力数据库。
如果安全很重要,passwd和shadow应该进行精简,以避免将用户密码复制出系统,并使在您从软盘启动时拒绝不必要的登录。
确保passwd至少包含root。如果您打算让其他用户登录,请确保其主目录和 shell 存在。
termcap,终端数据库,通常有几百千字节。您的启动/根磁盘上的版本应精简为仅包含您使用的终端,通常只是linux或linux-console条目。
其余的。它们目前可以工作,所以我让它们保持原样。
在这些文件中,我实际上只需要配置两个文件,而且它们应该包含的内容非常少。
rc应该包含
#!/bin/sh /bin/mount -av /bin/hostname Kangaroo |
fstab应该至少包含
/dev/ram0 / ext2 defaults /dev/fd0 / ext2 defaults /proc /proc proc defaults |
您的inittab应该更改,以便其sysinit行运行rc或将使用的任何基本启动脚本。此外,如果您想确保串口上的用户无法登录,请注释掉所有getty其中包括ttys或ttyS行末尾的设备。保留tty端口,以便您可以在控制台登录。
一个最小的inittab文件看起来像这样
id:2:initdefault: si::sysinit:/etc/rc 1:2345:respawn:/sbin/getty 9600 tty1 2:23:respawn:/sbin/getty 9600 tty2 |
中提到的文件名;如果inittab;如果init无法找到提到的程序,启动盘将挂起,您甚至可能不会收到错误消息。
请注意,某些程序无法移动到其他位置,因为其他程序已对其位置进行了硬编码。例如,在我的系统上,/etc/shutdown已在其中硬编码/etc/reboot。如果我移动reboot到/bin/reboot,然后发出一个shutdown命令,它将失败,因为它找不到reboot文件。
对于其余的,只需复制您/etc目录中的所有文本文件,以及您/etc目录中您不确定不需要的所有可执行文件。作为指导,请参阅 附录 C 中的示例列表。可能只需复制那些文件就足够了,但是系统差异很大,因此您不能确定您系统上的同一组文件与列表中的文件等效。唯一可靠的方法是从inittab开始,并弄清楚需要什么。
大多数系统现在使用一个/etc/rc.d/目录,其中包含用于不同运行级别的 shell 脚本。最小值是一个单一的rc脚本,但可能只需复制inittab和/etc/rc.d目录从您现有的系统,并修剪rc.d目录中的 shell 脚本,以删除与软盘系统环境无关的处理。
/bin目录是存放您需要执行基本操作的额外实用程序的便捷位置,例如 ls、mv、cat 和 dd 等实用程序。请参阅 附录 C 以获取 /bin 和/sbin目录中的文件示例列表。它不包括从备份还原所需的任何实用程序,例如 cpio、tar 和 gzip。那是因为我将这些程序放在单独的实用程序软盘上,以节省启动/根磁盘上的空间。一旦启动了启动/根磁盘,它就会被复制到 ramdisk,从而使软盘驱动器可以自由挂载另一个软盘,即实用程序软盘。我通常将其挂载为/usr.
实用程序软盘的创建在下面的 第 9.2 节中描述。最好保留用于编写备份的相同版本的备份实用程序的副本,这样您就不会浪费时间尝试安装无法读取备份磁带的版本。
![]() | 务必包含以下程序init, getty或等效程序,login, mount,一些能够运行您的 rc 脚本的 shell,从sh到 shell 的链接。 |
在/lib中,您放置必要的共享库和加载程序。如果在您的/lib目录中找不到必要的库,则系统将无法启动。如果您幸运的话,您可能会看到一条错误消息告诉您原因。
几乎每个程序都至少需要libc库,libc.so.N,其中 N 是当前版本号。检查您的/lib目录。文件libc.so.N通常是指向具有完整版本号的文件名的符号链接
% ls -l /lib/libc* -rwxr-xr-x 1 root root 4016683 Apr 16 18:48 libc-2.1.1.so* lrwxrwxrwx 1 root root 13 Apr 10 12:25 libc.so.6 -> libc-2.1.1.so* |
在这种情况下,您想要libc-2.1.1.so。要查找其他库,您应该遍历您计划包含的所有二进制文件,并使用 ldd 检查它们的依赖项。例如
% ldd /sbin/mke2fs libext2fs.so.2 => /lib/libext2fs.so.2 (0x40014000) libcom_err.so.2 => /lib/libcom_err.so.2 (0x40026000) libuuid.so.1 => /lib/libuuid.so.1 (0x40028000) libc.so.6 => /lib/libc.so.6 (0x4002c000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) |
请注意,某些库非常大,并且不容易放入您的根文件系统中。例如,libc.so上面列出的库大约有 4 兆字节。在将库复制到根文件系统时,您可能需要剥离库。有关说明,请参见 第 8 节。
在/lib您还必须包含库的加载程序。加载程序可以是ld.so(对于 A.OUT 库,现在不再常见)或ld-linux.so(对于 ELF 库)。较新版本的 ldd 会告诉您确切需要哪个加载程序,如上面的示例所示,但较旧的版本可能不会。如果您不确定您需要哪个,请在库上运行 file 命令。例如
% file /lib/libc.so.4.7.2 /lib/libc.so.5.4.33 /lib/libc-2.1.1.so /lib/libc.so.4.7.2: Linux/i386 demand-paged executable (QMAGIC), stripped /lib/libc.so.5.4.33: ELF 32-bit LSB shared object, Intel 80386, version 1, stripped /lib/libc-2.1.1.so: ELF 32-bit LSB shared object, Intel 80386, version 1, not stripped |
将您需要的特定加载程序复制到您正在构建的根文件系统。库和加载程序应仔细对照包含的二进制文件进行检查。如果内核无法加载必要的库,则内核可能会挂起,而不会显示错误消息。
您的系统可能需要动态加载的库,这些库对于ldd不可见。如果您不提供这些库,您可能在登录或使用启动盘时遇到问题。
如果您的系统使用 PAM(可插拔身份验证模块),您必须在启动盘上为其提供一些支持。简而言之,PAM 是一种用于验证用户身份并控制其对服务访问权限的复杂模块化方法。确定您的系统是否使用 PAM 的一种简单方法是运行ldd在您的login可执行文件上;如果输出包含libpam.so,您需要 PAM。
幸运的是,对于启动盘来说,安全性通常不是问题,因为任何可以物理访问计算机的人通常都可以为所欲为。因此,您可以通过创建一个简单的/etc/pam.conf文件在您的根文件系统中,如下所示
OTHER auth optional /lib/security/pam_permit.so OTHER account optional /lib/security/pam_permit.so OTHER password optional /lib/security/pam_permit.so OTHER session optional /lib/security/pam_permit.so |
此配置允许任何人完全访问您计算机上的文件和服务。如果您出于某种原因关心启动盘上的安全性,则必须将硬盘 PAM 设置的部分或全部复制到根文件系统。请务必仔细阅读 PAM 文档,并将
中所需的任何库复制到您的根文件系统。/lib/security到您的根文件系统上。
您还必须包含/lib/libpam.so在您的启动盘上。但是您已经知道这一点,因为您在/bin/login上运行了 ldd,它显示了此依赖项。
如果您使用的是 glibc(又名 libc6),您将不得不为名称服务做准备,否则您将无法登录。文件/etc/nsswitch.conf控制各种服务的数据库查找。如果您不打算从网络访问服务(例如,DNS 或 NIS 查找),您只需要准备一个简单的nsswitch.conf文件,如下所示
passwd: files shadow: files group: files hosts: files services: files networks: files protocols: files rpc: files ethers: files netmasks: files bootparams: files automount: files aliases: files netgroup: files publickey: files |
如果您计划从启动盘访问网络,您可能需要创建一个更详细的nsswitch.conf文件。请参阅nsswitch手册页以获取详细信息。您必须包含一个文件/lib/libnss_service.so.1对于您指定的每个服务。
如果您有一个模块化内核,您必须考虑在启动后可能要从启动盘加载哪些模块。如果您的备份磁带在软盘磁带上,您可能需要包含 ftape 和 zftape 模块;如果您有 SCSI 设备,则需要 SCSI 设备模块;如果您想在紧急情况下访问网络,则可能需要 PPP 或 SLIP 支持模块。
这些模块可以放置在/lib/modules。您还应该包含 insmod、rmmod 和 lsmod。根据您是否要自动加载模块,您可能还需要包含 modprobe、depmod 和 swapout。如果您使用 kerneld,请将其与/etc/conf.modules.
然而,使用模块的主要优点是您可以将非关键模块移动到实用程序磁盘并在需要时加载它们,从而减少根磁盘上的空间使用。如果您可能必须处理许多不同的设备,那么这种方法比构建一个内置许多驱动程序的大型内核更好。
![]() | 为了启动压缩的 ext2 文件系统,您必须内置 ramdisk 和 ext2 支持。它们不能作为模块提供。 |
一些系统程序,例如 login,如果文件/var/run/utmp和目录/var/log不存在,则会报错。所以
mkdir -p /mnt/var/{log,run} touch /mnt/var/run/utmp |
最后,在您设置完所有需要的库之后,运行 ldconfig 以重新创建/etc/ld.so.cache在根文件系统上。缓存告诉加载程序在哪里找到库。您可以使用以下命令执行此操作
ldconfig -r /mnt |
[1] | 此处介绍的目录结构仅用于根软盘。真正的 Linux 系统有一套更复杂和规范的策略,称为 文件系统层次结构标准,用于确定文件应放置在何处。) |