ROMFS - ROM 文件系统¶
这是一个相当简单的只读文件系统,主要用于安装盘的初始 RAM 磁盘。它的出现是为了满足在启动时链接模块的需求。使用此文件系统,你可以获得非常相似的功能,甚至可以拥有一个小型内核,其文件系统不会占用你办公室地下室的路由器功能所需的内存。
作为比较,较旧的 minix 和 xiafs(后者现已失效)文件系统,作为模块编译时需要超过 20000 字节,而 romfs 小于一页,大约 4000 字节(假设是 i586 代码)。在相同条件下,msdos 文件系统需要大约 30K(并且不支持设备节点或符号链接),而使用 nfsroot 的 nfs 模块大约需要 57K。此外,作为略不公平的比较,一个实际的救援磁盘使用 ext2 时占用了 3202 个块,而使用 romfs 时需要 3079 个块。
要创建这样一个文件系统,你需要一个名为 genromfs 的用户程序。它可以在 http://romfs.sourceforge.net/ 上找到。
顾名思义,romfs 也可以(高效地利用空间)用于各种只读介质,例如 (E)EPROM 磁盘,如果有人有这个动力的话... :)
但是,romfs 的主要目的是拥有一个非常小的内核,其中仅链接了此文件系统,然后可以使用当前的模块实用程序加载任何模块。它还可以用于运行某些程序来决定是否需要 SCSI 设备,甚至如果使用内核的“initrd”——初始 RAM 磁盘——功能,也可以稍后加载 IDE 或软盘驱动器。这并不是什么新鲜事,但是使用 romfs,你甚至可以省去 ext2 或 minix 甚至 affs 文件系统,直到你真正知道你需要它为止。
例如,发行版启动盘可以只包含 CD 磁盘驱动程序(可能还有 SCSI 驱动程序)和 ISO 9660 文件系统模块。内核可以足够小,因为它没有其他文件系统,例如相当大的 ext2fs 模块,然后可以在安装的后期阶段从 CD 加载该模块。另一个用途是用于恢复磁盘,当你从网络重新安装工作站时,你将可以从附近的服务器获得所有工具/模块,因此你不希望为此目的携带两个磁盘,仅仅因为它不适合 ext2。
romfs 像你期望的那样在块设备上运行,并且底层结构非常简单。每个可访问的结构都从 16 字节边界开始,以便快速访问。一个文件占用的最小空间是 32 字节(这是一个空文件,名称少于 16 个字符)。任何非空文件的最大开销是标头,以及名称和内容的 16 字节填充,也为 16+14+15 = 45 字节。然而,这种情况非常罕见,因为大多数文件名都长于 3 个字节,且短于 15 个字节。
文件系统的布局如下
offset content
+---+---+---+---+
0 | - | r | o | m | \
+---+---+---+---+ The ASCII representation of those bytes
4 | 1 | f | s | - | / (i.e. "-rom1fs-")
+---+---+---+---+
8 | full size | The number of accessible bytes in this fs.
+---+---+---+---+
12 | checksum | The checksum of the FIRST 512 BYTES.
+---+---+---+---+
16 | volume name | The zero terminated name of the volume,
: : padded to 16 byte boundary.
+---+---+---+---+
xx | file |
: headers :
每个多字节值(32 位字,从现在开始我将使用 longword 术语)必须是大端顺序。
前八个字节标识文件系统,即使对于非专业检查员也是如此。之后,在第 3 个 longword 中,它包含从该文件系统开始可以访问的字节数。第 4 个 longword 是前 512 个字节(或可以访问的字节数,以较小者为准)的校验和。应用的算法与 AFFS 文件系统中的相同,即 longword 的简单总和(再次假设大端量)。有关详细信息,请查阅源代码。选择此算法是因为它虽然不太可靠,但不需要任何表,并且非常简单。
以下字节现在是文件系统的一部分;每个文件头必须从 16 字节边界开始
offset content
+---+---+---+---+
0 | next filehdr|X| The offset of the next file header
+---+---+---+---+ (zero if no more files)
4 | spec.info | Info for directories/hard links/devices
+---+---+---+---+
8 | size | The size of this file in bytes
+---+---+---+---+
12 | checksum | Covering the meta data, including the file
+---+---+---+---+ name, and padding
16 | file name | The zero terminated name of the file,
: : padded to 16 byte boundary
+---+---+---+---+
xx | file data |
: :
由于文件头始终从 16 字节边界开始,因此在下一个 filehdr 指针中,最低 4 位将始终为零。这四个位用于模式信息。位 0..2 指定文件类型;而位 4 显示该文件是否可执行。如果未设置此位,则假定权限为世界可读,如果已设置此位,则假定为世界可执行;除了字符设备和块设备,它们永远不允许所有者以外的其他用户访问。每个文件的所有者都是用户和组 0,这对于预期用途来说应该永远不是问题。 8 个可能的值到文件类型的映射如下
0 |
硬链接 |
链接目标 [文件头] |
1 |
目录 |
第一个文件的头 |
2 |
普通文件 |
未使用,必须为零 [MBZ] |
3 |
符号链接 |
未使用,MBZ(文件数据是链接内容) |
4 |
块设备 |
16/16 位主/次设备号 |
5 |
字符设备 |
|
6 |
套接字 |
未使用,MBZ |
7 |
先进先出管道 |
未使用,MBZ |
请注意,硬链接在此文件系统中被专门标记,但它们的行为与你期望的一样(即共享 inode 号)。另请注意,你有责任不创建硬链接循环,并为目录创建所有 . 和 .. 链接。这通常由 genromfs 程序正确完成。请不要对套接字和 fifo 特殊文件上的可执行位用于特殊目的,它们将来可能具有其他用途。此外,请记住,只有普通文件和符号链接才应该具有非零大小字段;它们包含(填充后的)文件名之后可用的字节数。
另一件需要注意的是,romfs 在与 16 字节边界对齐的文件头和数据上工作,但是大多数硬件设备和块设备驱动程序无法处理小于块大小的数据。为了克服此限制,必须将文件系统的总大小填充到 1024 字节边界。
如果你对这个文件系统有任何问题或建议,请与我联系。但是,在希望我添加功能和代码之前请三思,因为此文件系统的主要和最重要的优势是代码量小。另一方面,不要惊慌,我没有收到那么多与 romfs 相关的邮件。现在我可以理解为什么艾弗里在 ARCnet 文档中写诗来获得更多反馈了。 :)
romfs 还有一个邮件列表,到目前为止,它还没有收到任何流量,因此欢迎你加入它来讨论你的想法。 :)
它由 ezmlm 运行,因此你可以通过发送消息到 romfs-subscribe@shadow.banki.hu 来订阅它,内容无关紧要。
待解决的问题
权限和所有者信息是类 Un*x 系统中非常重要的功能,但是 romfs 没有提供完整的功能。我从来没有觉得这有限制,但是其他人可能会觉得有限制。
文件系统是只读的,因此可以非常小,但是如果想要向文件系统写入_任何_内容,仍然需要一个可写的文件系统,从而否定了大小优势。可能的解决方案:将写入访问实现为编译时选项,或者为 RAM 磁盘实现一个新的、类似的小型可写文件系统。
由于仅要求文件在 16 字节边界上对齐,因此目前从文件系统中读取或执行文件可能不是最佳的。可以通过重新排序文件数据来解决此问题,使其大部分(即除了开始和结束)位于“自然”边界,从而可以将文件内容的大部分直接映射到 mm 子系统。
压缩可能是一个有用的功能,但是在我看来,内存是一个非常限制性的因素。
它在哪里使用?
它可以在 Intel 和 Motorola 之外的其他架构上工作吗?
玩得开心,
Janos Farkas <chexum@shadow.banki.hu>