no space left on device 错误可能源于 msgmni 值过小,它限制系统可创建的消息队列总数;该值默认由内核自动计算(如16~256),不足时需手动设为合理值(如1024)并执行 sysctl -p 生效。

报 No space left on device 错误,不是磁盘满了,而是系统消息队列资源耗尽了——核心问题在于 msgmni 值太小,它限制了系统能同时存在的消息队列总数,而不是单个队列大小。
为什么 ipcs -l 显示的 max queues system wide 和 /proc/sys/kernel/msgmni 不一致
内核 2.6.18 之后,msgmni 默认由内核自动计算(基于内存),但这个动态值可能远低于实际需求。而 ipcs -l 输出的 “max queues system wide” 正是这个 msgmni 的当前生效值。如果你手动写死 /etc/sysctl.conf 里的 kernel.msgmni,内核就不再自动调整,ipcs -l 就会立刻反映你设的值。
- 检查当前值:
cat /proc/sys/kernel/msgmni或sysctl kernel.msgmni - 查看是否被内核接管:
grep msgmni /proc/sys/kernel/—— 若输出为空或显示为 0,说明未显式设置,正由内核管理 - 自动计算值通常偏低(比如 16~256),高并发 IPC 场景下极易撞限
msgmni、msgmnb、msgmax 到底管什么
这三个参数互不替代,各司其职:
-
msgmni:系统级上限,决定最多能创建多少个独立的消息队列(msgget()调用次数上限) -
msgmnb:每个队列的总容量上限(字节),影响msgsnd()能否成功写入——注意:它不等于“最多存几条”,还要除以单条最大长度 -
msgmax:每条消息的字节数上限,直接影响struct msgbuf中mtext字段能填多长
例如:msgmnb=6553600 + msgmax=65536 → 单队列最多约 100 条消息;但若 msgmni=16,整个系统最多只能建 16 个这样的队列。
临时改和永久改,关键步骤不能漏
临时修改只对当前运行生效,重启即丢;永久修改必须让 sysctl 加载新配置,且需确认写入位置正确:
- 临时生效:
sudo sysctl -w kernel.msgmni=1024(建议先试这个,验证是否解决报错) - 永久生效:在
/etc/sysctl.conf末尾加一行kernel.msgmni = 1024,然后执行sudo sysctl -p - ⚠️ 容易踩坑:改完
/etc/sysctl.conf忘记sysctl -p,或写错格式(比如多了空格、少了等号、用了中文符号) - 验证是否加载成功:
sysctl kernel.msgmni输出应与你设置的值一致,且ipcs -l中 “max queues system wide” 同步更新
POSIX 消息队列(mq_open)不受这些参数控制
如果你用的是 mq_open()(而非 msgget()),那上面所有 kernel.msg* 参数都无效。POSIX 队列走的是另一套机制:
- 单队列最大消息数由
/proc/sys/fs/mqueue/msg_max控制(默认常为 10) - 单条消息最大字节数由
/proc/sys/fs/mqueue/msgsize_max控制(默认 8192) - 系统总队列数由
/proc/sys/fs/mqueue/queues控制 - 修改方式类似:
echo 256 | sudo tee /proc/sys/fs/mqueue/msg_max,或写入/etc/sysctl.conf对应路径
混用 System V 和 POSIX 消息队列时,务必分清调用路径,否则调大 msgmni 对 mq_open 完全没用。











