Tmpfs¶
Tmpfs 是一个文件系统,它将其所有文件保存在虚拟内存中。
tmpfs 中的所有内容都是临时的,因为不会在您的硬盘驱动器上创建任何文件。如果您卸载 tmpfs 实例,则其中存储的所有内容都将丢失。
tmpfs 将所有内容放入内核内部缓存中,并根据其包含的文件的大小进行增长和缩小,并且如果为 tmpfs 挂载启用了交换,则能够将不需要的页面交换到交换空间。 tmpfs 还支持 THP。
tmpfs 使用户空间可配置的几个选项扩展了 ramfs,这些选项在下面进一步列出和解释,其中一些选项可以使用文件系统的重新挂载(“mount -o remount ...”)动态地即时重新配置。可以调整 tmpfs 文件系统的大小,但不能将其大小调整到低于当前使用量的大小。 tmpfs 还支持 POSIX ACL 和受信任的扩展属性.*,安全.* 和用户.* 命名空间。 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 有以下用途
始终有一个您根本看不到的内核内部挂载。这用于共享匿名映射和 SYSV 共享内存。
此挂载不依赖于 CONFIG_TMPFS。如果未设置 CONFIG_TMPFS,则不会构建 tmpfs 的用户可见部分。但是内部机制始终存在。
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 共享内存。)
有些人(包括我)发现将它挂载在 /tmp 和 /var/tmp 上并拥有一个大的交换分区非常方便。 现在 tmpfs 文件的循环挂载确实有效,因此大多数发行版附带的 mkinitrd 应该可以使用 tmpfs /tmp 成功。
可能还有很多我不知道的 :-)
tmpfs 有三个用于调整大小的挂载选项
size |
此 tmpfs 实例的已分配字节数的限制。默认值是物理 RAM 的一半,不包括交换。如果您过度使用 tmpfs 实例,机器将会死锁,因为 OOM 处理程序将无法释放该内存。 |
nr_blocks |
与大小相同,但以 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”的 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 的内存策略将按指定的方式保存,以在文件创建时使用。 当任务在文件系统中分配文件时,将应用挂载选项内存策略,如果存在,则通过调用任务的 cpuset 约束来修改 NodeList [请参阅CPUSETS] 和任何可选标志,如下所述。 如果生成的 NodeLists 为空集,则文件的有效内存策略将恢复为“默认”策略。
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 选项。 它可以稍后在 tmpfs 已经挂载在 MountPoint 上时添加,方法是 'mount -o remount,mpol=Policy:NodeList 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 编号的文件的可能性;但是,一旦达到 33 位 inode 编号,可能会导致 glibc 出现 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, 2007 年 6 月 4 日
- 更新时间:
KOSAKI Motohiro, 2010 年 3 月 16 日
- 更新时间:
Chris Down, 2020 年 7 月 13 日
- 更新时间:
André Almeida, 2024 年 8 月 23 日