在 Linux 中,ipcs -m 的 bytes 列才是 System V 共享内存的真实容量,因为它直接读取内核中的 shmid_ds.shm_segsz 字段,反映的是 shmget() 创建时指定并经过页对齐后的固定大小,不会随着进程读写或运行状态变化而改变。

ipcs -m 依然是查看 System V 共享内存大小最直接、最可靠的方法,其中的 bytes 列展示的就是每一段共享内存对应的实际字节数。至于 free 或 top 里的 shared 字段,不要混淆——它统计的是进程之间共享的物理内存页,并不等同于 IPC 共享内存的大小。
为什么 ipcs -m 的 bytes 才代表真实大小
System V 共享内存段在 Linux 内核中是独立存在的,bytes 字段来源于内核结构体 shmid_ds.shm_segsz,表示创建时通过 shmget() 指定的 size 参数(按页对齐后保存),不会因为进程不断读写而动态增减。常见误区包括:
- 把
free -h输出中的shared误认为共享内存总量——实际上它只是对tmpfs和匿名页共享情况的粗略统计,并不包含 System V 共享内存段 - 使用
ps查看SHR列——那只是进程地址空间中“可能被共享”的映射部分,无法据此判断某段 IPC 共享内存是否存在或占用了多少 - 查看
/dev/shm/目录下文件大小——这只能反映 POSIX 共享内存(由shm_open()创建),与通过shmget()创建的 System V 共享内存完全不是同一种机制
快速定位大块共享内存或疑似泄漏:重点看 bytes 和 nattch
执行 ipcs -m 后,建议重点结合以下两列进行判断:
bytes很大(例如 >50MB)且nattch == 0→ 说明该共享内存段已经没有进程 attach,但没有执行shmctl(shmid, IPC_RMID, NULL)删除,通常属于典型的共享内存泄漏bytes中等(如 1–10MB)但nattch持续波动 → 可能存在进程频繁执行shmat()/shmdt(),这时可结合ipcs -m -p查看cpid/lpid,再通过ps -p PID -o pid,comm,args进一步确认具体进程行为- 如果想统计 System V 共享内存总占用,可使用
ipcs -m | tail -n +2 | awk '{sum += $4} END {print sum}'——这里要注意累计的是$4(bytes),不是$5(nattch)
查不到程序创建的共享内存?先确认使用的是哪类 API
如果你的程序使用的是 mmap() + /dev/shm/myseg,那么 ipcs -m 显示为空是正常现象——因为它只负责查看 System V 共享内存(shmget/shmctl)。这种情况下应改用其他命令:
- 查看 POSIX 共享内存:
ls -lh /dev/shm/(文件大小就是对应共享内存对象大小) - 查看整体占用情况:
df -h /dev/shm(其容量受shmmax和shmall限制,但与 System V 的/proc/sys/kernel/shm*参数并不是同一套机制) - 确认程序是否真的使用了 POSIX 共享内存:检查代码中是否有
shm_open()或open("/dev/shm/xxx"),如果有,通常就属于这一类
很多人在排查 Linux 共享内存问题时最容易忽略的,正是这一点:System V 共享内存段一旦创建成功,就会脱离进程生命周期,作为独立对象保留在系统中;即使相关进程全部退出,只要没有显式删除(shmctl(..., IPC_RMID) 或 ipcrm -m shmid),它仍会持续占用内核资源,而 bytes 的数值也始终不会变化。
