bigywater.tech
Docker · 96

/dev/shm:默认 64MB 对共享内存程序的影响

浏览器、数据库、多进程程序在容器里莫名崩溃,往往因为 /dev/shm 只有 64 MiB。这篇实测默认大小、写满时 dd 与 mmap 的不同表现(报错与 SIGBUS)、它算不算容器的内存、以及怎么在容器之间共享。

64 MiB
默认容器 /dev/shm 的大小
退出码 135
默认 /dev/shm 下 mmap 写满 100 MiB 共享内存时进程的退出码(SIGBUS)
+80.5 MiB
往 /dev/shm 写 80 MiB 后容器内存的增加量

大小

实测 · 本机执行输出
  默认:/dev/shm 大小 64 MiB;挂载选项 rw,nosuid,nodev,noexec,relatime,size=65536k
  --shm-size 256m:/dev/shm 大小 256 MiB;挂载选项 rw,nosuid,nodev,noexec,relatime,size=262144k
  --shm-size 1g:/dev/shm 大小 1024 MiB;挂载选项 rw,nosuid,nodev,noexec,relatime,size=1048576k
  docker inspect 的 HostConfig.ShmSize(默认容器) = 67108864 字节

默认 64 MiB,--shm-size 可以改,单位 b/k/m/g。挂载选项带 noexec。

write 写满

实测 · 本机执行输出
  默认 64 MiB,写 100 MiB:65+0 records in | 64+0 records out | 67108864 bytes (64.0MB) copied, 0.130363 seconds, 490.9MB/s | 67108864
  --shm-size 128m,写 100 MiB:100+0 records in | 100+0 records out | 104857600 bytes (100.0MB) copied, 0.166911 seconds, 599.1MB/s | 104857600

用 write 写满返回 ENOSPC:dd 只写进 64 MiB,第 65 个块写不下。

mmap 写满

实测 · 本机执行输出
  默认 64 MiB,共享内存 100 MiB:退出码 135;输出:ftruncate 成功,大小 100 MiB(稀疏,还没占用)
  --shm-size 128m,共享内存 100 MiB:退出码 0;输出:ftruncate 成功,大小 100 MiB(稀疏,还没占用) | 所有页都写完了

用 mmap 的程序(Python 的 shared_memory、浏览器、很多数据库)在创建时不会报错,写到没空间的页时才被 SIGBUS 杀死,退出码 135,很难一眼看出原因。

占内存

实测 · 本机执行输出
  往 /dev/shm 写 80 MiB:memory.current 5.2 → 85.7 MiB(增加 80.5 MiB)
  --memory 64m、--shm-size 200m,往 /dev/shm 写 120 MiB:docker run 退出码 0;输出:dd 之后的退出码 0 | Killed;容器 ExitCode=0 OOMKilled=True

/dev/shm 是内存文件系统,写进去的内容算在容器的内存里;--memory 比 --shm-size 小的话,先触发的是 OOM,不是 No space left(与 c24 的 tmpfs 一致)。

共享

实测 · 本机执行输出
  b 通过 --ipc container:a 加入 a 的 IPC 命名空间后,能读到 a 写在 /dev/shm 的文件吗?from-a
  两者的 IPC 命名空间相同吗?True

/dev/shm 属于 IPC 命名空间,--ipc shareable 加 --ipc container:名字 让两个容器共用同一个 /dev/shm。

分步演示

/dev/shm
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。mmap 测试用 Python 3.12 的 multiprocessing.shared_memory,每 4096 字节写一个字节让所有页都被触碰;dd 与 mmap 各一次;内存取自 /sys/fs/cgroup/memory.current(docker exec 读取,含 exec 进程的几 MiB);OOM 由 --memory 64m 触发;实验后已删除容器
    • 没有验证:浏览器(Chrome / Chromium)实际崩溃场景与 --disable-dev-shm-usage 的效果、--ipc host 对 /dev/shm 的影响、Kubernetes 的 emptyDir medium: Memory 替代方案、/dev/shm 与 hugepages
    京ICP备2026067502号-1京公网安备11010502063487号