Tmpfs

Tmpfs是一个文件系统,它将其所有文件保存在虚拟内存中。

tmpfs中的所有内容都是临时的,因为不会在硬盘驱动器上创建任何文件。如果卸载 tmpfs 实例,则其中存储的所有内容都将丢失。

tmpfs将所有内容放入内核内部缓存中,并会扩展和缩小以适应它包含的文件,并且如果为 tmpfs 挂载启用了交换,则能够将不需要的页面交换到交换空间。 tmpfs 也支持 THP。

tmpfs 扩展了 ramfs,并提供了一些用户空间可配置的选项,这些选项在下面列出和进一步解释,其中一些选项可以使用文件系统的重新挂载(‘mount -o remount ...’)动态地重新配置。 tmpfs 文件系统可以调整大小,但不能调整到低于其当前使用量的大小。 tmpfs 还支持 POSIX ACL 以及 trusted.*、security.* 和 user.* 命名空间的扩展属性。 ramfs 不使用交换,并且无法修改 ramfs 文件系统的任何参数。 ramfs 文件系统的大小限制取决于可用的内存量,因此如果使用 ramfs,必须小心不要耗尽内存。

tmpfs 和 ramfs 的替代方案是使用 brd 创建 RAM 磁盘 (/dev/ram*),这允许在物理 RAM 中模拟块设备磁盘。 要写入数据,只需在此 ramdisk 之上创建一个常规文件系统即可。 与 ramfs 一样,brd ramdisks 无法交换。 brd ramdisks 也在初始化时配置大小,并且无法动态调整其大小。 与 brd ramdisks 相反,tmpfs 有其自己的文件系统,它根本不依赖于块层。

由于 tmpfs 完全位于页面缓存中,并且可以选择位于交换空间上,因此所有 tmpfs 页面都将显示为 /proc/meminfo 中的“Shmem”和 free(1) 中的“Shared”。 请注意,这些计数器还包括共享内存(shmem,参见 ipcs(1))。 获取计数的更可靠方法是使用 df(1) 和 du(1)。

tmpfs 具有以下用途

  1. 始终存在一个内核内部挂载点,您根本看不到它。 这用于共享匿名映射和 SYSV 共享内存。

    此挂载点不依赖于 CONFIG_TMPFS。 如果未设置 CONFIG_TMPFS,则不会构建 tmpfs 的用户可见部分。 但是内部机制始终存在。

  2. glibc 2.2 及更高版本期望 tmpfs 挂载在 /dev/shm 上,以用于 POSIX 共享内存(shm_open、shm_unlink)。 将以下行添加到 /etc/fstab 应该可以解决此问题

    tmpfs   /dev/shm        tmpfs   defaults        0 0
    

    请记住创建您打算在 tmpfs 上挂载的目录(如果需要)。

    SYSV 共享内存_不需要_此挂载。 内部挂载用于此目的。 (在 2.3 内核版本中,必须挂载 tmpfs 的前身 (shm fs) 才能使用 SYSV 共享内存。)

  3. 有些人(包括我)发现将其挂载在 /tmp 和 /var/tmp 上非常方便,并且拥有一个大的交换分区。 现在 tmpfs 文件的循环挂载可以工作,因此大多数发行版附带的 mkinitrd 应该可以成功使用 tmpfs /tmp。

  4. 可能还有更多我不知道的 :-)

tmpfs 具有三个用于调整大小的挂载选项

size

此 tmpfs 实例的已分配字节数的限制。 默认值为物理 RAM 的一半(不包括交换)。 如果 tmpfs 实例过大,则机器将死锁,因为 OOM 处理程序将无法释放该内存。

nr_blocks

与 size 相同,但以 PAGE_SIZE 的块为单位。

nr_inodes

此实例的最大 inode 数。 默认值为物理 RAM 页数的一半,或者(在具有高内存的计算机上)低内存 RAM 页数,以较低者为准。

这些参数接受后缀 k、m 或 g 分别表示千兆、兆兆和吉兆,并且可以在重新挂载时更改。 size 参数也接受后缀 %,以将此 tmpfs 实例限制为物理 RAM 的该百分比:当未指定 size 或 nr_blocks 时,默认值为 size=50%

如果 nr_blocks=0(或 size=0),则该实例中的块将不受限制; 如果 nr_inodes=0,则 inode 将不受限制。 通常,使用此类选项进行挂载是不明智的,因为它允许任何具有写入访问权限的用户耗尽计算机上的所有内存; 但可以增强在大量 CPU 的系统中的该实例的可伸缩性,从而密集地使用它。

如果 nr_inodes 不为 0,则用于 inode 的有限空间也会被扩展属性占用:“df -i“‘s IUsed 和 IUse% 增加,IFree 减少。

当内存短缺时,tmpfs 块可能会被交换出去。 tmpfs 具有禁用其使用交换的挂载选项

noswap

禁用交换。 重新挂载必须尊重原始设置。 默认情况下,启用交换。

tmpfs 还支持透明巨页,这需要使用 CONFIG_TRANSPARENT_HUGEPAGE 配置的内核,并且您的系统支持巨页 (has_transparent_hugepage(),这是特定于体系结构的)。为此的挂载选项是

huge=never

不要分配巨页。 这是默认值。

huge=always

每次需要新页面时,尝试分配巨页。

huge=within_size

仅当巨页完全位于 i_size 内时才分配巨页。 还要尊重 madvise(2) 提示。

huge=advise

仅当使用 madvise(2) 请求时才分配巨页。

另请参见 透明巨页支持,其中描述了 sysfs 文件 /sys/kernel/mm/transparent_hugepage/shmem_enabled:它可用于在紧急情况下拒绝所有 tmpfs 挂载上的巨页,或强制在所有 tmpfs 挂载上使用巨页进行测试。

tmpfs 还支持带有以下挂载选项的配额

quota

用户和组配额记帐和强制在此挂载上启用。 Tmpfs 正在使用在挂载时初始化的隐藏系统配额文件。

usrquota

用户配额记帐和强制在此挂载上启用。

grpquota

组配额记帐和强制在此挂载上启用。

usrquota_block_hardlimit

设置全局用户配额块硬限制。

usrquota_inode_hardlimit

设置全局用户配额 inode 硬限制。

grpquota_block_hardlimit

设置全局组配额块硬限制。

grpquota_inode_hardlimit

设置全局组配额 inode 硬限制。

所有与配额相关的挂载选项都不能在重新挂载时设置或更改。

配额限制参数接受后缀 k、m 或 g 分别表示千兆、兆兆和吉兆,并且无法在重新挂载时更改。 默认全局配额限制对任何和所有用户/组/项目(root 除外)生效,前提是首次访问用户/组/项目 ID 的配额条目 - 通常是在挂载后首次创建具有特定 ID 所有权的 inode。 换句话说,限制不会初始化为零,而是使用这些挂载选项提供的特定值初始化。 可以随时为任何用户/组 ID 更改限制,就像通常可以一样。

请注意,tmpfs 配额不支持用户命名空间,因此如果在用户命名空间内启用了配额,则不会进行 uid/gid 转换。

tmpfs 具有一个挂载选项,用于为此实例中的所有文件设置 NUMA 内存分配策略(如果启用了 CONFIG_NUMA) - 可以通过 ‘mount -o remount ...’ 动态调整

mpol=default

使用进程分配策略(参见 set_mempolicy(2))

mpol=prefer:Node

首选从给定的节点分配内存

mpol=bind:NodeList

仅从 NodeList 中的节点分配内存

mpol=interleave

首选依次从每个节点分配

mpol=interleave:NodeList

依次从 NodeList 的每个节点分配

mpol=local

首选从本地节点分配内存

NodeList 格式是以逗号分隔的十进制数字和范围的列表,范围是两个以连字符分隔的十进制数字,范围中最小和最大的节点编号。 例如,mpol=bind:0-3,5,7,9-15

具有有效 NodeList 的内存策略将被保存,如指定的那样,以供文件创建时使用。 当任务在文件系统中分配文件时,挂载选项内存策略将应用于具有 NodeList 的文件,如果有的话,则由调用任务的 cpuset 约束修改[参见CPUSETS] 和任何可选标志(如下所列)。 如果生成的 NodeLists 为空集,则文件的有效内存策略将恢复为“default”策略。

NUMA 内存分配策略具有可选标志,这些标志可以与其模式结合使用。 这些可选标志可以在挂载 tmpfs 时指定,方法是在 NodeList 之前将其附加到模式。 有关所有可用内存分配策略模式标志及其对内存策略的影响的列表,请参见 NUMA 内存策略

=static         is equivalent to        MPOL_F_STATIC_NODES
=relative       is equivalent to        MPOL_F_RELATIVE_NODES

例如,mpol=bind=static:NodeList 等效于 MPOL_BIND | MPOL_F_STATIC_NODES 的分配策略。

请注意,如果运行的内核不支持 NUMA,尝试使用 mpol 选项挂载 tmpfs 将会失败; 并且如果其节点列表指定了不在线的节点,则也会失败。 如果您的系统依赖于该 tmpfs 的挂载,但有时运行未构建 NUMA 功能的内核(可能是一个安全的恢复内核),或者在线节点更少,则建议从自动挂载选项中省略 mpol 选项。 可以稍后通过 ‘mount -o remount,mpol=Policy:NodeList MountPoint’ 在 tmpfs 已经挂载到 MountPoint 上时添加它。

要指定初始根目录,您可以使用以下挂载选项

mode

作为八进制数的权限

uid

用户 ID

gid

组 ID

这些选项对重新挂载没有任何影响。 您可以使用 chmod(1)、chown(1) 和 chgrp(1) 在已挂载的文件系统上更改这些参数。

tmpfs 具有一个挂载选项,用于选择它将在 32 位还是 64 位 inode 号上换行

inode64

使用 64 位 inode 号

inode32

使用 32 位 inode 号

在 32 位内核上,inode32 是隐式的,并且在挂载时拒绝 inode64。 在 64 位内核上,CONFIG_TMPFS_INODE64 设置默认值。 inode64 避免了单个设备上具有相同 inode 号的多个文件的可能性; 但存在 glibc 在达到 33 位 inode 号后失败并出现 EOVERFLOW 的风险 - 如果一个长期存在的 tmpfs 被 32 位应用程序访问,这些应用程序非常古老,以至于打开大于 2GiB 的文件会失败并出现 EINVAL。

因此,‘mount -t tmpfs -o size=10G,nr_inodes=10k,mode=700 tmpfs /mytmpfs’ 将在 /mytmpfs 上为您提供 tmpfs 实例,该实例可以在 10240 个 inode 中分配 10GB RAM/SWAP,并且只有 root 可以访问它。

tmpfs 具有以下用于不区分大小写查找支持的挂载选项

casefold

使用给定的参数作为编码标准在此挂载点启用 casefold 支持。 目前仅支持 UTF-8 编码。 如果没有使用参数,它将加载最新的可用 UTF-8 编码。

strict_encoding

在此挂载点启用严格编码(默认情况下禁用)。 在此模式下,文件系统拒绝创建包含无效 UTF-8 字符名称的文件和目录。

此选项不会使整个文件系统不区分大小写。 仍然需要通过翻转空目录中的 +F 属性来为每个目录设置 casefold 标志。 尽管如此,新目录将继承该属性。 挂载点本身不能设置为不区分大小写。

示例

$ mount -t tmpfs -o casefold=utf8-12.1.0,strict_encoding fs_name /mytmpfs
$ mount -t tmpfs -o casefold fs_name /mytmpfs
作者:

Christoph Rohland <cr@sap.com>, 1.12.01

更新:

Hugh Dickins, 4 June 2007

更新:

KOSAKI Motohiro, 16 Mar 2010

更新:

Chris Down, 13 July 2020

更新:

André Almeida, 23 Aug 2024