如何在多线程中关闭 malloc() 的 mmap 用法?



似乎malloc()更喜欢使用mmap()在多线程程序中分配空间。我刚刚尝试设置M_TRIM_THRESHOLDM_MMAP_MAX关闭mmap使用,但失败了:

// Turn off malloc trimming.
mallopt(M_TRIM_THRESHOLD, -1);
// Turn off mmap usage.
mallopt(M_MMAP_MAX, 0);

一个简单的测试代码段如下:

#include <malloc.h>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
void alloc_assert()
{
// Turn off malloc trimming.
mallopt(M_TRIM_THRESHOLD, -1);
// Turn off mmap usage.
mallopt(M_MMAP_MAX, 0);
void* p = malloc(100);
printf("size_t(p): %zun", size_t(p));
assert(size_t(p) < 0x100000000000l);
}
void* thread_func(void *arg)
{
alloc_assert();
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t thr[2];
int data = 0;
// Multi-thread enabled.
if (pthread_create(&thr[0], NULL, &thread_func, (void*) &data) != 0)
{
printf("Create thread errorn");
}
pthread_join(thr[0], NULL);
//alloc_assert();
return 0;
}

输出如下:

size_t(p): 140154111002816
a.out: main.cpp:37: void alloc_assert(): Assertion `size_t(p) < 0x100000000000l' failed.
[1]    154060 abort      ./a.out

malloc()在高地址而不是普通堆地址上分配空间。但是,如果我们main()中的代码更改为以下内容:

int main()
{
alloc_assert();
return 0;
}

输出为:

size_t(p): 31775776

malloc()没有使用mmap(),而是在普通堆上分配了空间。我想是否可以关闭多线程程序中malloc()mmap()的使用?

我的环境配置:

Thread model: posix
gcc version 5.2.0 (GCC)
Linux fsdev32 2.6.32-573.el6.x86_64

总结

看起来原因是glibc的malloc使用了多个malloc"竞技场",并为每个新线程提供了自己的竞技场,无论您M_MMAP_MAX什么

设置。如果该领域有空间,glibc 会满足您的malloc()要求。

您可以使用mallopt(M_ARENA_MAX, 1)禁用它。

我通过导入#include <malloc.h>(glibc 特定)并更改您的代码以显示malloc_stats()统计信息来确认这一点:

malloc_stats();
puts("");
void* p = malloc(100);
malloc_stats();

这将打印:

Arena 0:
system bytes     =     135168
in use bytes     =       1328
Total (incl. mmap):
system bytes     =     135168
in use bytes     =       1328
max mmap regions =          0
max mmap bytes   =          0
Arena 0:
system bytes     =     135168
in use bytes     =       1328
Arena 1:
system bytes     =     135168
in use bytes     =       2336
Total (incl. mmap):
system bytes     =     270336
in use bytes     =       3664
max mmap regions =          0
max mmap bytes   =          0

我们可以看到如何添加具有135168字节的新Arena 1

strace -fy -e mmap ./yourprogram,我们可以看到这个竞技场的创建:

[pid  8704] mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7efefe1a7000
[pid  8704] munmap(0x7efefe1a7000, 31821824) = 0
[pid  8704] munmap(0x7eff04000000, 35287040) = 0
[pid  8704] mprotect(0x7eff00000000, 135168, PROT_READ|PROT_WRITE) = 0
size_t(p): 139633681762496; address: 0x7eff000008c0

所以看起来glibcmmap新竞技场的一些内存,释放它的一部分,然后mprotect()135168许多字节 - 就像那个竞技场显示的一样多malloc_stats()

这向我表明man mallopt

Setting this parameter to 0 disables the use of mmap(2)
for servicing large allocation requests.

并不完全正确:当它想要创建一个新竞技场时,它仍然会mmap

您显然可以使用以下方法避免这种情况:

mallopt(M_ARENA_MAX, 1);

相关内容

  • 没有找到相关文章

最新更新