FreeBSD允许你为短期内存磁盘创建由系统RAM支持的文件系统。
从内存中读取比访问磁盘上的文件快得多,这使得内存支持的文件系统成为某些应用程序的绝佳优化。
不过,与内存中的其他所有内容一样,在系统关闭时,将会丢失此文件系统。
FreeBSD支持两种不同的基于RAM的磁盘:tmpfs和memory disks。
虽然它们背后有相似的概念,但底层代码完全不同,它们扮演这不同的角色。
对于长时间运行的系统上的内存支持的文件系统,使用tmpfs。
memort disk更灵活,但更适合短期使用(除非仔细配置)或安装磁盘映像。
tmpfs中的tmp并不是temporary的意思。就像/tmp一样,就是字面意思的tmp。
对于快速内存支持的/tmp和类似的文件系统,使用tmpfs。
不过,不要在看到包含tmp的路径的任何地方部署tmpfs——记住,/var/tmp中的数据是为了在重新启动后存活。
你可以将tmpfs用于应用程序锁文件和其他临时数据,在这些数据中,速度可以提高性能。虽然旧版本的tmpfs存在问题,但从FreeBSD10开始,它已被广泛部署并被认为已可用于生产环境。
当你挂载一个tmpfs,它自动创建一个文件系统:
xxxxxxxxxx
# mount –t tmpfs tmpfs /tmp
你也可以在/etc/fstab中创建条目,使其在系统启动时自动挂载:
xxxxxxxxxx
tmpfs /tmp tmpfs rw,mode=1777 0 0
如果允许用户挂载文件系统(通过将sysctl vfs.usermount 设置为1),他们可以创建和挂载tmpfs文件系统。然而,具有此设置的机器通常属于单个用户。
接下来考虑一些tmpfs选项。
如果fmpfs设置过大,可能会耗尽系统内存。
使用mount选项size设置tmpfs的最大大小:
xxxxxxxxxx
# mount –o size=1g -t tmpfs tmpfs /mnt
如果你挂载多个没有最大大小的tmpfs文件系统,它们都会认为它们的最大大小等于整个可用内存和交换空间。这意味着两个半满的tmpfs实例会占满整个内存。
减少内存耗尽的一种方式是使用maxfilesize选项限制tmpfs上可以存储的文件大小。/tmp或/var/tmp中的大多数文件都很小,在大多数系统上,任何文件都不应超过几兆字节。
在这里,我在此tmpfs上的任何文件上设置了最大文件大小为10MB:
xxxxxxxxxx
# mount -o maxfilesize=10m -t tmpfs tmpfs /tmp/
将一个大文件复制到您的tmpfs,您将收到“文件太大”错误。
如果你想限制tmpfs上可以存在的文件数量,可以考虑限制inode的数量。
虽然每个文件和目录都需要索引节点,但索引节点的数量与文件和目录的数量并不直接相关。
你会尝试一下这个限制,可靠它是否适合你,以及它需要如何调整:
xxxxxxxxxx
# mount -o inodes=10k -t tmpfs tmpfs /tmp
对于大多数系统上的/tmp来说,一万个索引节点应该就足够了。
您还可以使用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交换备份内存磁盘:
xxxxxxxxxx
# mdmfs -s 16m md /mnt
上面md选项表示后面指定挂载点。
使用-X选项可以查看mdmfs在幕后的工作:
xxxxxxxxxx
# mdmfs -X -s 16m md /mnt
DEBUG: running: /sbin/mdconfig -a -t swap -s 16m
DEBUG: running: /sbin/newfs -U /dev/md0
DEBUG: running: /sbin/mount /dev/md0 /mnt
所有其他mdmfs命令行选项都是关于更改其他程序的行为。
传统上,交换回内存磁盘从不将用过的内存返回给系统。一旦写入内存磁盘,内存就会被消耗。如果你需要一个大的内存磁盘,必须为它永久分配内存。这是FreeBSD包含tmpfs的原因之一。
不过,如果内存磁盘上的文件系统支持TRIM,FreeBSD8.1及更高版本将向系统返回未使用的内存。
在mdmfs中使用-t标志启用TRIM。TRIM可能只对长寿命的大内存磁盘很重要。
我们有许多mdmfs选项来调整底层内存磁盘。
我们大多数人不关心磁盘的几何形状(geometry)、模拟磁盘转速或临时文件系统中每个索引节点的块数。以下是常见的选项。
-M选项使用malloc-backed磁盘。
使用-F选项将UFS文件系统放在现有文件上并挂载它。这是破坏性的——磁盘上存在的任何文件系统都将被销毁。如果你想在不破坏内容的情况下挂载现有的UFS映像文件,请添加-P标志:
xxxxxxxxxx
# mdmfs -PF ufsfs.img md /media/
你可以在命令行中指定设备节点,而不是使用下一个可用的内存磁盘设备节点。
这里,我们告诉mdmfs使用设备md13:
xxxxxxxxxx
# mdmfs –s 16M md13 /mnt
新的文件系统使用newfs默认值,这对于内存磁盘来说可能没有意义。具体来说,软更新在临时文件系统上没有用。
也不是noasync挂载,因为崩溃后无法恢复此磁盘。
使用-S禁用软更新;使用-o提供任何挂载选项:
xxxxxxxxxx
# mdmfs -S -o async -s 16m md /mnt
使用-w指定一个用户和一个组来拥有内存磁盘。你必须同时指定所有者和组——只列出其中之一是错误的。同样,使用-p标志定义新设备的权限:
xxxxxxxxxx
# mdmfs –p 700 -w mwl:mwl -s 16m md /home/mwl/mnt
用户拥有此存储设备的完全所有权。
虽然mdmfs简化了创建内存磁盘,但你需要使用mdconfig销毁它们。
销毁内存磁盘可以释放设备使用的内存。
要查找磁盘设备,可运行mount并查找包含内存磁盘的分区:
xxxxxxxxxx
/dev/md86 on /mnt (ufs, asynchronous, local)
/mnt分区构建在内存设备/dev/md86上。卸载分区,然后使用mdconfig销毁设备:
xxxxxxxxxx
# umount /mnt
# mdconfig –d –u 86
使用umount卸载与任何其他UFS文件系统完全一样。使用mdconfig直接管理内存设备。-d表示销毁,-u表示设备节点号。上面示例销毁了内存磁盘/dev/md86。设备使用的内存现在被释放可用了。
内存磁盘可能会累积,几个月后,您可能会忘记哪个磁盘做什么以及如何配置。mdconfig的-l选项显示所有活动内存磁盘设备节点。添加–v标志以显示每个图标的详细信息。
xxxxxxxxxx
# mdconfig -lv
md0 swap 16M
md1 vnode 690M /home/mwl/ FreeBSD-disc1.iso
此主机有两个内存磁盘,一个支持交换的16 MB文件系统,一个连接到ISO。
虽然mdmfs允许您在文件上使用文件系统,但文件必须首先存在。使用dd(1)为文件系统创建文件。dd命令是复制和更改文件的通用工具,但现在它最常用于创建磁盘映像。
使用dd需要一点数学运算。它复制一定数量的给定大小的块。您需要计算出生成所需大小的文件需要多少个该大小的块。选择块大小有一个完整的游戏,通过一些研究,你可以选择最有效的块大小,但我发现使用1 MB的块在现代硬件上可以提供合理的性能。那么,如果你想要一个1GB的磁盘映像,你需要多少个1MB的块?硬件制造商会说1000,而大多数系统管理员会说1024。我将完全回避这个问题,并创建一个512 MB的文件。
一旦你知道你需要多少个街区,你就需要一个地方来获取这些街区。无关内容的最快来源是空设备/dev/zero。在这里,我创建了一个512 MB的图像文件,里面装满了东西。
xxxxxxxxxx
# dd if=/dev/zero of=ufs2.img bs=1m count=512
if=给出了输入文件,或者我从中复制的源文件。of=定义输出文件,bs是块大小,count是块数。所以我复制了512个1MB的块……绝对没有数据。结果是一个512 MB的文件。
如果你需要大文件,数GB甚至数TB,dd的运行速度可能会非常慢。FreeBSD允许您创建任意大小的空文件或稀疏文件。稀疏文件被标记为具有特定大小,但它只占用磁盘上的一个块。一旦你把东西放进去,稀疏文件就会增长。使用-s选项truncate(1)以创建稀疏文件。给它一个参数,文件的大小。
下面创建一个512MB稀疏文件:
xxxxxxxxxx
# truncate –s 512M sparse.img
结果是一个声称达到所需大小的文件:
xxxxxxxxxx
# ls -lh sparse.img
-rw-r--r-- 1 root mwl 512M Sep 2 13:39 sparse.img
然而,使用ls或du来获取此文件所使用的磁盘块数则是另外一个答案:
xxxxxxxxxx
# ls -s sparse.img
1 sparse.img
此文件使用一个文件系统块。在这个磁盘上,有512个字节。
稀疏的文件很棒。你可以在低GB的磁盘空间中容纳数万亿个这样的小文件。但是,当您将数据写入稀疏文件时,它们会扩展。只需使用稀疏文件来支持文件系统,您就可以在不创建任何新文件的情况下填充物理磁盘。使用mdmfs在此文件上创建文件系统会膨胀底层文件,就像每次磁盘写入一样。
稀疏的文件永远不会缩小,他们只能长大。即便如此,如果您需要在2 TB的ZFS池中安装一个大部分为空的10 TB磁盘映像,您可能会发现它们很有用。
在/etc/fstab文件中列出内存磁盘会告诉FreeBSD在启动时自动创建它们。设备名为md,文件系统类型为mfs。在选项列中,列出用于创建此设备的任何命令行mdmfs(8)选项,如下所示:
xxxxxxxxxx
md /mnt mfs rw,-s16m
当从/etc/fstab挂载时,内存磁盘是全局可写的,并且设置了粘滞位。这些权限适用于/tmp,但不适用于其他任何地方。将权限指定为挂载选项,但请记住/etc/fstab不允许额外的空格。用逗号分隔各种选项,并消除命令行选项与其参数之间的任何空格。
xxxxxxxxxx
md /home/mwl/mnt mfs rw,-p700,-wmwl:mwl,-s16m
您可以使用mdmfs挂载UFS磁盘映像,但更常见的是挂载ISO或UDF映像。
虽然FreeBSD的tar(1)可以通过libarchive从ISO映像中提取文件,但这通常是多余的。此外,ISO图像是只读的。您可以对使用tar(1)提取的文件造成手指损伤,但ISO可以防止篡改。此外,libarchive无法从纯UDF映像中提取文件。
有时,最简单的选择是装载磁盘映像。
要挂载磁盘映像,请使用mdconfig(8)将文件附加到支持vnode的内存设备。当你只给出一个文件名作为参数时,mdconfig会假设你想将该文件用作文件系统。
xxxxxxxxxx
# mdconfig FreeBSD-10.2-RELEASE-amd64-disc1.iso
md1
作为响应,您将获得此内存磁盘的设备节点md1。现在使用正确的mount命令来挂载这个文件系统。
xxxxxxxxxx
# mount –t cd9660 /dev/md1 /media
请记住,除非另有说明,否则mount(8)假定所有文件系统都是UFS。
访问完磁盘映像后,卸载映像并销毁内存磁盘设备,就像销毁任何其他内存设备一样。
您可以在/etc/fstab中指定一个内存设备并将其附加到磁盘映像。将文件系统类型指定为mfs。指定文件系统是只读的,并使用-F标志给出磁盘映像的路径。在启动时,此条目创建内存设备md10,将其连接到/iso/stuff.iso,并将其挂载到/stuff。
xxxxxxxxxx
md10 /stuff mfs ro,-F/iso/stuff.iso 0 0
系统需要在启动过程的早期访问磁盘映像。如果图像不可用,则进程将挂起。例如,您可能需要对主目录中的磁盘映像使用noauto。
通过结合noauto挂载选项和autofs(第12章),系统可以仅在需要时挂载映像,并在不使用时自动卸载映像。
您还可以在/etc/rc.conf中使用mdconfig_md条目在启动时配置内存磁盘,然后使用更简单的/etc/fstab条目,但这种方法不如纯/etc/fstab条目的灵活。