内存分配阈值(mmap vs malloc)
Posted
技术标签:
【中文标题】内存分配阈值(mmap vs malloc)【英文标题】:Memory allocation threshold (mmap vs malloc) 【发布时间】:2017-12-15 15:10:29 【问题描述】:我想指出我是新手,所以我想尽我所能理解/解释它。
我基本上是想弄清楚由于我的项目的内存限制,是否可以将内存分配保持在阈值以下。
这是当前使用第三方 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);
【问题讨论】:
恐怕没有简单的答案......例如文件读取或写入通常是mmap。 上述代码不会尝试分配超过 30Mb 的空间,除非您要求。您是否有理由一开始就不能避免请求过多的内存? 我正在调用一种由于内存问题导致终止的加密方法,因为我正在超过给定的 30mb 阈值。所以我跟踪了这个函数的分配。你是说如果我只是告诉它分配 20mb 它仍然可以执行仅分配 20mb 的操作吗?我已经更新了我的原始帖子以显示对 alloc_region 的调用 为什么不编写自己的 malloc 来跟踪分配了多少 @Useless 我认为您现在正在查看代码,但我现在尝试分配更少的内存时遇到了错误。我认为需要一个新问题。 【参考方案1】:我基本上是想弄清楚由于我的项目的内存限制,是否可以将内存分配保持在阈值以下。
在 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
将失败,例如调用 malloc(3) 触发 mmap
的特定使用也会失败。
我的印象是我可以使用 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。
【讨论】:
以上是关于内存分配阈值(mmap vs malloc)的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核 内存管理内存管理架构 ④ ( 内存分配系统调用过程 | 用户层 malloc free | 系统调用层 brk mmap | 内核层 kmalloc | 内存管理流程 )