共享内存:shmget 失败:设备上没有剩余空间——如何增加限制?

共享内存:shmget 失败:设备上没有剩余空间——如何增加限制?

我在程序中多次调用 shmget,以获取平均大小为 85840 字节的 shm。我成功获取了大约 32771 个 shm,然后 shmget 不返回 shm,而是返回错误:“设备上没有剩余空间”。

我已将内核限制增加到:

$ sysctl -A|grep shm
kernel.shmmax = 33554432
kernel.shmall = 1677721600
kernel.shmmni = 409600

但问题仍然存在。为什么?

我是否也必须在 /etc/security/limits.conf 中放入一些内容?我只有“user - nofile 1000000”,因为该程序打开的文件数量与 shms 差不多。

这是免费的输出

$ free
          total       used       free     shared    buffers     cached
Mem:       8150236    7261676     888560          0     488100    3270792
-/+ buffers/cache:    3502784    4647452 
Swap:     12287992     554692   11733300

和 ipcs

$ ipcs -lm                                                                         

------ Shared Memory Limits --------
max number of segments = 409600
max seg size (kbytes) = 1638400
max total shared memory (kbytes) = 6710886400
min seg size (bytes) = 1

由于我假设 shm 能够被换出,所以应该有足够的空间。

答案1

事实证明,内核中的 shmmni 限制为 32768:

#define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */

在文件中 ...version.../include/linux/ipc.h

因此,除了重新编译内核之外,共享内存段的数量也存在硬性限制。

答案2

使用ipcs -l来检查实际生效的限制,并ipcs -a查看ipcs -m正在使用的内容,以便您可以比较输出。查看列nattch:是否存在未附加进程的段,这些段在进程退出时未被删除(这通常意味着程序崩溃)?ipcrm可以清除它们,但如果这是一台测试机器,则重新启动会更快(并确保您对限制的更改被采纳)。

您的内核参数似乎很奇怪。特别是,shmall它是页面数,而不是字节数,并且默认页面大小为 4kB(运行getconf PAGESIZE以检查您正在使用的内容)。您有多少 TB 的 RAM?

现在,您说您获得了大约 32771 个共享内存段,也就是大约 32768(或 2 的 15 次方),这表明有符号的 16 位 int 是限制因素。您正在运行什么内核(因为这会有自己的限制)?这两者可能相关。

答案3

分配shmget()一个新的共享内存段,而您似乎使用了很多(考虑到您的 limits.conf),您是否可能使用了太多的共享内存段?我对调用没有太多经验shmget(),但在我看来,可能打开的文件数(1000000)大于允许的共享内存段数量(SHMMNI),后者为 409600。

答案4

做就是了:

sysctl -a | grep shm

并找到您的kernel.shmmni条目。在您的 中将该条目值加倍/etc/sysctl.conf

相关内容