我在程序中多次调用 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
。