Skip to content

第九十三章:tmpfs

斩灵期

涉及内核源码:

林小源穿过一片薄雾,走进了一个奇异的领域。这里的地面是半透明的,脚下能看到流动的光点——那是内存中的数据在涌动。

"这是什么地方?"林小源蹲下身,手掌贴在地面上,感受到一股温热的脉动。

"tmpfs。"一个年轻的声音从身后传来。林小源转身,看到一个轻盈的身影——它的身体几乎是透明的,只有轮廓在微微发光。"内存文件系统。"

"内存文件系统?"林小源站起来,"你的数据不存磁盘?"

tmpfs 摇了摇头,透明的发丝在空中飘动:"不用磁盘。我所有的数据都在 RAM 里——你脚下的每一个光点,都是一个内存页。读写速度是内存速度,比磁盘快几十倍。"

林小源踩了踩地面,确实感觉比之前走过的 ext4 和 btrfs 的领地要轻盈得多。"那你岂不是……很快?"

"非常快。"tmpfs 微微一笑,"但有一个代价——重启之后,一切都会消失。我不持久。"

"消失?"林小源有些惊讶,"那谁会用你?"

"很多人。"tmpfs 指了指远处,"看到那边的 /tmp 目录了吗?那是我的领地。程序运行时产生的临时文件,放在那里最合适——用完就扔,重启自动清理。还有 /run,存放 PID 文件和 socket 文件;/dev/shm,POSIX 共享内存。"

林小源跟着 tmpfs 走在半透明的地面上,忽然注意到前方有一片区域颜色更深,光线更密集。

"那是 swap。"tmpfs 说,"当内存不够用的时候,我可以把一部分数据交换到磁盘上的 swap 分区。这是我和 ramfs 最大的区别。"

"ramfs?"林小源想起了另一个虚拟文件系统。

"ramfs 是我的前辈。"tmpfs 的语气里带着一丝尊敬,"它也是基于内存的文件系统,但它没有大小限制——可以无限增长,直到把所有内存吃光。这很危险。"

"所以你加了限制?"

"对。"tmpfs 说,"我可以设置 size 参数限制最大大小,还可以设置 限制最大 inode 数。而且我可以使用 swap——内存不够时,把冷数据交换出去,腾出空间给热数据。"

林小源蹲下身,仔细观察脚下的光点。有些光点明亮活跃,有些则暗淡缓慢。"这些是在区分冷热数据?"

tmpfs 点头:"内核的页面回收算法会帮我管理。长时间不访问的页面会被交换到 swap,腾出物理内存。"

林小源来到 /dev/shm 的入口。这里的光线格外明亮,空气中弥漫着一种奇特的振动——像是多个进程在同时读写同一个区域。

"这是 POSIX 共享内存。"tmpfs 说,"多个进程可以通过读写 /dev/shm 下的文件进行通信。因为数据在内存中,所以速度比通过磁盘文件通信快得多。"

"为什么不直接用管道或 socket?"

tmpfs 沉吟了一下:"管道和 socket 是字节流,适合顺序通信。共享内存是随机访问的——多个进程可以直接读写同一块内存区域的任意位置,适合大数据量的并行处理。"

林小源看着两个光点——两个进程——同时在一块共享区域上读写,数据在它们之间飞速传递。

"但共享内存也有风险。"tmpfs 的语气变得严肃,"没有同步机制的话,多个进程同时写入会导致数据竞争。你需要信号量或者互斥锁来保护共享区域。"

"我记住了。"林小源说。

tmpfs 轻轻挥手,整个领域闪烁了一下:"我虽然虚幻——重启就消失——但在那短暂的存在里,我是最快的文件系统。"

c
/*
 * tmpfs 的特点:
 *
 * 1. 基于内存
 *    数据存储在 RAM 中
 *    可以使用 swap
 *    重启后丢失
 *
 * 2. 动态大小
 *    不需要预先分配大小
 *    随使用量增长
 *    受限于 RAM + swap
 *
 * 3. 快速访问
 *    没有磁盘 I/O
 *    读写速度 = 内存速度
 *
 * 4. 支持所有文件操作
 *    创建、删除、读写
 *    权限、所有者
 *
 * tmpfs 的用途:
 *   /tmp — 临时文件
 *   /run — 运行时数据
 *   /dev/shm — 共享内存
 *   /sys/fs/cgroup — cgroup 文件系统
 *
 * 挂载 tmpfs:
 *   mount -t tmpfs tmpfs /tmp
 *   mount -t tmpfs -o size=1G tmpfs /tmp
 */

printf("=== tmpfs — 内存文件系统 ===\n\n");

printf("tmpfs 的特点:\n");
printf("  基于内存: 数据在 RAM 中\n");
printf("  动态大小: 随使用量增长\n");
printf("  快速访问: 内存速度\n");
printf("  易失性: 重启后丢失\n\n");

printf("--- tmpfs 的用途 ---\n");
printf("/tmp:\n");
printf("  临时文件\n");
printf("  程序运行时创建\n");
printf("  重启后清理\n\n");
printf("/run:\n");
printf("  运行时数据\n");
printf("  PID 文件\n");
printf("  socket 文件\n\n");
printf("/dev/shm:\n");
printf("  POSIX 共享内存\n");
printf("  进程间通信\n\n");

printf("--- tmpfs vs ramfs ---\n");
printf("ramfs:\n");
printf("  基于内存\n");
printf("  不能使用 swap\n");
printf("  可以无限增长(危险)\n\n");
printf("tmpfs:\n");
printf("  基于内存\n");
printf("  可以使用 swap\n");
printf("  有大小限制\n\n");

printf("--- 挂载选项 ---\n");
printf("mount -t tmpfs -o size=1G,nr_inodes=100k tmpfs /tmp\n");
printf("  size: 最大大小\n");
printf("  nr_inodes: 最大 inode 数\n\n");

printf("--- tmpfs 的优势 ---\n");
printf("1. 速度: 内存速度访问\n");
printf("2. 简单: 不需要磁盘分区\n");
printf("3. 灵活: 动态大小\n");
printf("4. 清洁: 重启后自动清理\n");

道藏笔记

内核启示

tmpfs 是基于内存的文件系统——数据全在 RAM 里,读写速度是内存速度,比磁盘快几十倍。代价是重启之后一切消失,不持久。

它的用途比想象中广。/tmp 是临时文件的家,程序运行时产生的临时数据放那里,用完就扔,重启自动清理。/run 存放 PID 文件和 socket 文件。/dev/shm 是 POSIX 共享内存,多个进程通过读写这里的文件通信,比管道和 socket 快得多——因为数据在内存里,是随机访问的。

跟前辈 ramfs 比,tmpfs 加了大小限制和 swap 支持。ramfs 可以无限增长直到吃光所有内存,很危险。tmpfs 可以设 size 参数限制最大大小,内存不够时还能把冷数据交换到 swap。内核的页面回收算法帮你管理冷热数据。


破关试炼

tmpfs 之试

tmpfs 常被挂到哪个共享内存目录,让数据待在内存里而非普通磁盘文件中?

答对后才能继续滑动和进入下一章。

以修仙之名,悟内核之道