即使有大量可用内存

时间:2018-06-01 09:00:05

标签: c linux memory

我正在尝试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

1 个答案:

答案 0 :(得分:0)

这似乎与超过一半的系统内存限制有关。试着用1MB不到一半的总系统工作正常,1MB以上就失败了。

不确定联机帮助页是否过时或者是什么,发布到lkml以查看是否有人知道。

编辑:原来这实际上是由于/ dev / shm上的tmpfs大小限制(这是shm_open创建它的文件的位置)。增加限制可以解决问题。