内存分配阈值(mmap vs malloc)

时间:2017-07-11 13:52:16

标签: c memory memory-management malloc mmap

我想指出我是新手,所以我想尽力理解/解释它。

我基本上试图弄清楚由于项目的内存限制,是否有可能将内存分配保持在一个阈值之下。

以下是目前使用第三方libsodium分配内存的方法:

alloc_region(escrypt_region_t *region, size_t size)
{
    uint8_t *base, *aligned;
#if defined(MAP_ANON) && defined(HAVE_MMAP)
    if ((base = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE,
#ifdef MAP_NOCORE
                                 MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
#else
                                 MAP_ANON | MAP_PRIVATE,
#endif
                                 -1, 0)) == MAP_FAILED)
        base = NULL; /* LCOV_EXCL_LINE */
    aligned  = base;
#elif defined(HAVE_POSIX_MEMALIGN)
    if ((errno = posix_memalign((void **) &base, 64, size)) != 0) {
        base = NULL;
    }
    aligned = base;
#else
    base = aligned = NULL;
    if (size + 63 < size)
        errno = ENOMEM;
    else if ((base = (uint8_t *) malloc(size + 63)) != NULL) {
        aligned = base + 63;
        aligned -= (uintptr_t) aligned & 63;
    }
#endif
    region->base    = base;
    region->aligned = aligned;
    region->size    = base ? size : 0;

    return aligned;
}

因此,例如,这当前调用posix_memalign来分配(例如)32mb的内存。 32mb超过我给我的'内存上限'(但不会因内存容量大得多而引发内存警告,这正是我'允许'使用的内容)

从一些谷歌搜索,我的印象是我可以使用mmap和虚拟内存。 我可以看到上面的函数已经实现了一些mmap,但从未调用过。

是否可以转换上面的代码,以便我永远不会超过我的30mb内存限制?

根据我的理解,如果这个分配超过我的可用内存,它会自动分配在虚拟内存中吗?那么我可以强迫这种情况发生并假装我的可用空间低于可用空间吗?

感谢任何帮助

更新

/* Allocate memory. */
    B_size = (size_t) 128 * r * p;
    V_size = (size_t) 128 * r * N;
    need   = B_size + V_size;
    if (need < V_size) {
        errno = ENOMEM;
        return -1;
    }
    XY_size = (size_t) 256 * r + 64;
    need += XY_size;
    if (need < XY_size) {
        errno = ENOMEM;
        return -1;
    }
    if (local->size < need) {
        if (free_region(local)) {
            return -1;
        }
        if (!alloc_region(local, need)) {
            return -1;
        }
    }
    B  = (uint8_t *) local->aligned;
    V  = (uint32_t *) ((uint8_t *) B + B_size);
    XY = (uint32_t *) ((uint8_t *) V + V_size);

1 个答案:

答案 0 :(得分:2)

  

我基本上试图弄清楚由于项目的内存限制,是否有可能将内存分配保持在一个阈值之下。

在Linux或POSIX系统上,您可以考虑将setrlimit(2)RLIMIT_AS一起使用:

         This is the maximum size of the process's virtual memory
          (address space) in bytes.  This limit affects calls to brk(2),
          mmap(2), and mremap(2), which fail with the error ENOMEM upon
          exceeding this limit.  

超过此限制,mmap会失败,因此会失败,例如调用触发mmap特定用途的malloc(3)

  

我的印象是我可以使用mmap

请注意,malloc(3)会调用mmap(2)(或有时sbrk(2) ...)从内核中检索(虚拟)内存,从而增加virtual address space。但是,malloc通常更喜欢重用以前的free - d内存(如果可用)。并且free通常不会调用munmap(2)来释放内存块,而是希望将其保留在将来malloc - s中。实际上,大多数C标准库在“小”和“大”分配之间进行隔离(实际上,对于千兆字节,malloc将使用mmap,而相应的free将立即mmap )。

另请参阅mallopt(3)madvise(2)。如果您需要将某些页面(由mmap获取)锁定到物理 RAM中,请考虑mlock(2)

另请参阅this回答(解释特定流程使用的RAM概念并不那么容易)。

对于malloc相关错误(包括memory leaks),请使用valgrind