内存与 OOM58 条

tmpfs 占用内存排查

tmpfs 上的文件直接消耗内存并计入 Shmem;df 看用量、du 找文件、/proc/meminfo 的 Shmem 看总量,容器 /dev/shm 与 /tmp 是高发区。

tmpfs 与内存的关系

tmpfs 是基于内存的文件系统,其中的文件直接消耗物理内存并计入 /proc/meminfo 的 Shmem。排查占用要分三层看:df -h 看挂载点用量与容量上限、du 与 lsof 找具体文件、meminfo 的 Shmem 看全局总量。容器环境里 /dev/shm 与 /tmp 是高发区。特别要注意:tmpfs 占用的页不会被 drop_caches 释放,只有删除文件(或换出)才能真正归还内存。

基本信息

查看用量df -h /dev/shm /tmp
内存口径/proc/meminfo 的 Shmem;容器内看 memory.stat 的 shmem
默认容量通常为物理内存的一半(依发行版与配置而定)
容量限制挂载参数 size=、nr_inodes=,可用 remount 调整
释放方式删除文件或卸载;drop_caches 无效
可换出性shmem 页可以被换出到 swap

典型使用场景

  • 容器内存无故增长:检查 /dev/shm 里是否留有大文件
  • 应用用 /dev/shm 做共享内存缓存但未清理,长期累积
  • /tmp 被当作临时存储写满,间接吃掉大量内存
  • 核查 df 与 meminfo:tmpfs 占用只记在内存、不计入磁盘容量
  • 为容器调整 /dev/shm 容量,避免默认值过小导致业务失败

排查步骤

排查步骤
df -h /dev/shm /tmp  # 看 tmpfs 的容量上限与已用量
grep -E '^Shmem' /proc/meminfo  # 全局 tmpfs 占用总量
grep -E '^shmem ' /sys/fs/cgroup/myapp.slice/memory.stat  # 容器视角的 tmpfs 占用
sudo du -sh /dev/shm/* 2>/dev/null | sort -h | tail  # 找出占用最大的文件
sudo lsof +D /dev/shm | head  # 确认文件是否仍被进程持有(已删除但未释放)
sudo mount -o remount,size=256M /dev/shm  # 调小上限,注意已用超过新值时会被拒绝

查看入口对照

查看项入口说明
挂载点用量df -h /dev/shm /tmp含容量上限与已用量
全局总量/proc/meminfo 的 Shmem所有 tmpfs 挂载的合计
容器占用memory.stat 的 shmem该 cgroup 内的 tmpfs 占用
具体文件du + lsof定位大文件与已删除但被持有的文件
删除文件后内存不一定立刻归还:只要还有进程持有文件句柄,容量就仍被占用。这种情况下要用 lsof 找到持有者,重启或关闭对应进程才能释放。
容器运行时通常给 /dev/shm 设置较小的默认容量(常见 64MB 量级),需要更大共享内存的应用必须通过运行时参数显式调大,否则会写入失败而不是单纯变慢。

易错点

  • 对 tmpfs 执行 drop_caches 期望释放:tmpfs 页不受该操作影响,只有删文件才有效
  • 只看 df 不看 meminfo:tmpfs 占用计入内存而不计入磁盘,容易漏账
  • df 显示满但 du 很小:说明存在已删除但被进程持有的文件,需用 lsof 或重启进程处理
  • 忽略容器运行时的 /dev/shm 默认限制:应用报写入失败却查不到磁盘问题
  • 缩小容量时已用超过新上限:remount 会被拒绝,需要先清理文件再调整

数据来源与参考

  • Linux 内核 Documentation/filesystems/tmpfs.rst
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌