我正在尝试mlock()一个~32GB的shm_open()'地址范围,即使有足够的内存且没有设置限制(rlimit无限制,以root身份运行),ENOMEM意外失败。< / p>
代码,无错误处理,基本上是:
shm_fd = shm_open(handle, (O_RDWR | O_CREAT), (S_IRWXU | S_IRWXG | S_IRWXO));
ftruncate(shm_fd, channel->sled_size)
channel->sled = mmap(NULL, channel->sled_size, (PROT_READ | PROT_WRITE), (MAP_SHARED | MAP_NORESERVE), shm_fd, 0);
mlock(channel->sled, channel->sled_size) /* Fails with ENOMEM. */
这适用于几个较小的映射(例如2M,20MB),但32GB映射失败。这是在64GB总内存的系统上(几乎所有内存都是免费的)。最大锁定内存是无限制的(但以root身份运行无论如何都不起作用)。内核是4.4.127。
在mlock()手册页中,由于以下原因,它可以返回ENOMEM,其中任何一个都不适用:
ENOMEM(Linux 2.6.9及更高版本)调用者具有非零RLIMIT_MEMLOCK软资源限制,但尝试锁定的内存超过允许的限制。 如果进程具有特权(CAP_IPC_LOCK),则不会强制执行此限制。
ENOMEM( Linux 2.4及更早版本)调用进程试图锁定超过一半的RAM。
ENOMEM某些指定的地址范围与流程地址空间中的映射页面不对应。
我所看到的最接近的原因是“试图锁定超过一半的RAM”,但是手册页指定它只是Linux 2.4及更早版本而且我运行的是4.4.127。
另一件奇怪的事情是,如果我在进程运行时查看htop,mlock()会在返回错误之前分配大约32GB的内存。检查/ dev / shm中的shm对象也表示它已经分配了大约32GB的块:
Size: 35641991168 Blocks: 66007032 IO Block: 4096 regular file
有什么想法吗?
谢谢, - 亚历克斯。
编辑:
仔细检查确切的内存量表明它正好占系统总内存的一半,这让我怀疑手册页是错误的并且RAM限制的一半仍然适用于4.4.127
66007168 * 1024 = 67591340032 /* Total system memory (per free command) */
66007032 * 512 = 33795600384 /* Allocated blocks (per stat command). */
33795600384 / 67591200768 = 0.5
答案 0 :(得分:0)
这似乎与超过一半的系统内存限制有关。试着用1MB不到一半的总系统工作正常,1MB以上就失败了。
不确定联机帮助页是否过时或者是什么,发布到lkml以查看是否有人知道。
编辑:原来这实际上是由于/ dev / shm上的tmpfs大小限制(这是shm_open创建它的文件的位置)。增加限制可以解决问题。