第五章:内存文件系统

FreeBSD允许你为短期内存磁盘创建由系统RAM支持的文件系统。

从内存中读取比访问磁盘上的文件快得多,这使得内存支持的文件系统成为某些应用程序的绝佳优化。

不过,与内存中的其他所有内容一样,在系统关闭时,将会丢失此文件系统。

FreeBSD支持两种不同的基于RAM的磁盘:tmpfs和memory disks。

虽然它们背后有相似的概念,但底层代码完全不同,它们扮演这不同的角色。

对于长时间运行的系统上的内存支持的文件系统,使用tmpfs。

memort disk更灵活,但更适合短期使用(除非仔细配置)或安装磁盘映像。

tmpfs(5)

tmpfs中的tmp并不是temporary的意思。就像/tmp一样,就是字面意思的tmp。

对于快速内存支持的/tmp和类似的文件系统,使用tmpfs。

不过,不要在看到包含tmp的路径的任何地方部署tmpfs——记住,/var/tmp中的数据是为了在重新启动后存活。

你可以将tmpfs用于应用程序锁文件和其他临时数据,在这些数据中,速度可以提高性能。虽然旧版本的tmpfs存在问题,但从FreeBSD10开始,它已被广泛部署并被认为已可用于生产环境。

当你挂载一个tmpfs,它自动创建一个文件系统:

你也可以在/etc/fstab中创建条目,使其在系统启动时自动挂载:

如果允许用户挂载文件系统(通过将sysctl vfs.usermount 设置为1),他们可以创建和挂载tmpfs文件系统。然而,具有此设置的机器通常属于单个用户。

接下来考虑一些tmpfs选项。

tmpfs 大小

如果fmpfs设置过大,可能会耗尽系统内存。

使用mount选项size设置tmpfs的最大大小:

如果你挂载多个没有最大大小的tmpfs文件系统,它们都会认为它们的最大大小等于整个可用内存和交换空间。这意味着两个半满的tmpfs实例会占满整个内存。

减少内存耗尽的一种方式是使用maxfilesize选项限制tmpfs上可以存储的文件大小。/tmp或/var/tmp中的大多数文件都很小,在大多数系统上,任何文件都不应超过几兆字节。

在这里,我在此tmpfs上的任何文件上设置了最大文件大小为10MB:

将一个大文件复制到您的tmpfs,您将收到“文件太大”错误。

如果你想限制tmpfs上可以存在的文件数量,可以考虑限制inode的数量。

虽然每个文件和目录都需要索引节点,但索引节点的数量与文件和目录的数量并不直接相关。

你会尝试一下这个限制,可靠它是否适合你,以及它需要如何调整:

对于大多数系统上的/tmp来说,一万个索引节点应该就足够了。

tmpfs 权限

您还可以使用uid、gid和mode选项控制tmpfs的所有权和权限。一个实际的/tmp目录应该是全局可写的,并且设置了sticky位,所以一定要使用选项mode=1777。如果tmpfs是针对特定用户或应用程序帐户的,请为该用户分配tmpfs的所有权。

对于更复杂的内存备份磁盘,请考虑传统的内存磁盘。

内存磁盘

memory disk是一种临时存储设备。

尽管有这个名字,但内存磁盘并不总是被视为磁盘的内存块。它可以是这样的设备,但它可能会使用文件或交换空间作为后备存储。

存储设备在重启时消失。

FreeBSD支持四种类型的内存磁盘:malloc-backed、swap-backed、vnode-bakced和null。

创建和挂载内存盘

mdmfs实用程序是创建通用内存磁盘的方便包装器。可以使用mdconfig和newfs等程序,但mdmfs会为你打包所有东西。

你只要知道要使用的磁盘大小、内存磁盘的类型和挂载点。mdmfs命令默认为交换备份内存磁盘,这是最常见的。

即使允许非特权用户挂载可移动介质,他们也可以创建内存磁盘。

使用-s标志指定文件系统大小。在这里,在/mnt上创建了一个16MB交换备份内存磁盘:

上面md选项表示后面指定挂载点。

使用-X选项可以查看mdmfs在幕后的工作:

所有其他mdmfs命令行选项都是关于更改其他程序的行为。

内存磁盘内存使用情况

传统上,交换回内存磁盘从不将用过的内存返回给系统。一旦写入内存磁盘,内存就会被消耗。如果你需要一个大的内存磁盘,必须为它永久分配内存。这是FreeBSD包含tmpfs的原因之一。

不过,如果内存磁盘上的文件系统支持TRIM,FreeBSD8.1及更高版本将向系统返回未使用的内存。

在mdmfs中使用-t标志启用TRIM。TRIM可能只对长寿命的大内存磁盘很重要。

mdmfs 选项

我们有许多mdmfs选项来调整底层内存磁盘。

我们大多数人不关心磁盘的几何形状(geometry)、模拟磁盘转速或临时文件系统中每个索引节点的块数。以下是常见的选项。

-M选项使用malloc-backed磁盘。

使用-F选项将UFS文件系统放在现有文件上并挂载它。这是破坏性的——磁盘上存在的任何文件系统都将被销毁。如果你想在不破坏内容的情况下挂载现有的UFS映像文件,请添加-P标志:

你可以在命令行中指定设备节点,而不是使用下一个可用的内存磁盘设备节点。

这里,我们告诉mdmfs使用设备md13:

新的文件系统使用newfs默认值,这对于内存磁盘来说可能没有意义。具体来说,软更新在临时文件系统上没有用。

也不是noasync挂载,因为崩溃后无法恢复此磁盘。

使用-S禁用软更新;使用-o提供任何挂载选项:

使用-w指定一个用户和一个组来拥有内存磁盘。你必须同时指定所有者和组——只列出其中之一是错误的。同样,使用-p标志定义新设备的权限:

用户拥有此存储设备的完全所有权。

销毁内存盘

虽然mdmfs简化了创建内存磁盘,但你需要使用mdconfig销毁它们。

销毁内存磁盘可以释放设备使用的内存。

要查找磁盘设备,可运行mount并查找包含内存磁盘的分区:

/mnt分区构建在内存设备/dev/md86上。卸载分区,然后使用mdconfig销毁设备:

使用umount卸载与任何其他UFS文件系统完全一样。使用mdconfig直接管理内存设备。-d表示销毁,-u表示设备节点号。上面示例销毁了内存磁盘/dev/md86。设备使用的内存现在被释放可用了。

查看内存盘

内存磁盘可能会累积,几个月后,您可能会忘记哪个磁盘做什么以及如何配置。mdconfig的-l选项显示所有活动内存磁盘设备节点。添加–v标志以显示每个图标的详细信息。

此主机有两个内存磁盘,一个支持交换的16 MB文件系统,一个连接到ISO。

文件中的文件系统

虽然mdmfs允许您在文件上使用文件系统,但文件必须首先存在。使用dd(1)为文件系统创建文件。dd命令是复制和更改文件的通用工具,但现在它最常用于创建磁盘映像。

使用dd需要一点数学运算。它复制一定数量的给定大小的块。您需要计算出生成所需大小的文件需要多少个该大小的块。选择块大小有一个完整的游戏,通过一些研究,你可以选择最有效的块大小,但我发现使用1 MB的块在现代硬件上可以提供合理的性能。那么,如果你想要一个1GB的磁盘映像,你需要多少个1MB的块?硬件制造商会说1000,而大多数系统管理员会说1024。我将完全回避这个问题,并创建一个512 MB的文件。

一旦你知道你需要多少个街区,你就需要一个地方来获取这些街区。无关内容的最快来源是空设备/dev/zero。在这里,我创建了一个512 MB的图像文件,里面装满了东西。

if=给出了输入文件,或者我从中复制的源文件。of=定义输出文件,bs是块大小,count是块数。所以我复制了512个1MB的块……绝对没有数据。结果是一个512 MB的文件。

如果你需要大文件,数GB甚至数TB,dd的运行速度可能会非常慢。FreeBSD允许您创建任意大小的空文件或稀疏文件。稀疏文件被标记为具有特定大小,但它只占用磁盘上的一个块。一旦你把东西放进去,稀疏文件就会增长。使用-s选项truncate(1)以创建稀疏文件。给它一个参数,文件的大小。

下面创建一个512MB稀疏文件:

结果是一个声称达到所需大小的文件:

然而,使用ls或du来获取此文件所使用的磁盘块数则是另外一个答案:

此文件使用一个文件系统块。在这个磁盘上,有512个字节。

稀疏的文件很棒。你可以在低GB的磁盘空间中容纳数万亿个这样的小文件。但是,当您将数据写入稀疏文件时,它们会扩展。只需使用稀疏文件来支持文件系统,您就可以在不创建任何新文件的情况下填充物理磁盘。使用mdmfs在此文件上创建文件系统会膨胀底层文件,就像每次磁盘写入一样。

稀疏的文件永远不会缩小,他们只能长大。即便如此,如果您需要在2 TB的ZFS池中安装一个大部分为空的10 TB磁盘映像,您可能会发现它们很有用。

内存磁盘和 /etc/fstab

在/etc/fstab文件中列出内存磁盘会告诉FreeBSD在启动时自动创建它们。设备名为md,文件系统类型为mfs。在选项列中,列出用于创建此设备的任何命令行mdmfs(8)选项,如下所示:

当从/etc/fstab挂载时,内存磁盘是全局可写的,并且设置了粘滞位。这些权限适用于/tmp,但不适用于其他任何地方。将权限指定为挂载选项,但请记住/etc/fstab不允许额外的空格。用逗号分隔各种选项,并消除命令行选项与其参数之间的任何空格。

 

磁盘映像

您可以使用mdmfs挂载UFS磁盘映像,但更常见的是挂载ISO或UDF映像。

虽然FreeBSD的tar(1)可以通过libarchive从ISO映像中提取文件,但这通常是多余的。此外,ISO图像是只读的。您可以对使用tar(1)提取的文件造成手指损伤,但ISO可以防止篡改。此外,libarchive无法从纯UDF映像中提取文件。

有时,最简单的选择是装载磁盘映像。

要挂载磁盘映像,请使用mdconfig(8)将文件附加到支持vnode的内存设备。当你只给出一个文件名作为参数时,mdconfig会假设你想将该文件用作文件系统。

作为响应,您将获得此内存磁盘的设备节点md1。现在使用正确的mount命令来挂载这个文件系统。

请记住,除非另有说明,否则mount(8)假定所有文件系统都是UFS。

访问完磁盘映像后,卸载映像并销毁内存磁盘设备,就像销毁任何其他内存设备一样。

磁盘映像和/etc/fstab

您可以在/etc/fstab中指定一个内存设备并将其附加到磁盘映像。将文件系统类型指定为mfs。指定文件系统是只读的,并使用-F标志给出磁盘映像的路径。在启动时,此条目创建内存设备md10,将其连接到/iso/stuff.iso,并将其挂载到/stuff。

系统需要在启动过程的早期访问磁盘映像。如果图像不可用,则进程将挂起。例如,您可能需要对主目录中的磁盘映像使用noauto。

通过结合noauto挂载选项和autofs(第12章),系统可以仅在需要时挂载映像,并在不使用时自动卸载映像。

您还可以在/etc/rc.conf中使用mdconfig_md条目在启动时配置内存磁盘,然后使用更简单的/etc/fstab条目,但这种方法不如纯/etc/fstab条目的灵活。