美文网首页
头文件malloc.h:函数 mallopt()的选项

头文件malloc.h:函数 mallopt()的选项

作者: 阿群1986 | 来源:发表于2020-02-21 15:35 被阅读0次

下面以一个例子来说明内存分配的原理:

情况一、malloc小于128k的内存,使用brk分配内存,将_edata往高地址推(只分配虚拟空间,不对应物理内存(因此没有初始化),第一次读/写数据时,引起内核缺页中断,内核才分配对应的物理内存,然后虚拟地址空间建立映射关系),如下图:

1、进程启动的时候,其(虚拟)内存空间的初始布局如图1所示。

其中,mmap内存映射文件是在堆和栈的中间(例如libc-2.2.93.so,其它数据文件等),为了简单起见,省略了内存映射文件。

_edata指针(glibc里面定义)指向数据段的最高地址。

2、进程调用A=malloc(30K)以后,内存空间如图2:

  malloc函数会调用brk系统调用,将_edata指针往高地址推30K,就完成虚拟内存分配。

你可能会问:只要把_edata+30K就完成内存分配了?

事实是这样的,_edata+30K只是完成虚拟地址的分配,A这块内存现在还是没有物理页与之对应的,等到进程第一次读写A这块内存的时候,发生缺页中断,这个时候,内核才分配A这块内存对应的物理页。也就是说,如果用malloc分配了A这块内容,然后从来不访问它,那么,A对应的物理页是不会被分配的。

3、进程调用B=malloc(40K)以后,内存空间如图3。

图(1) 图(2)图(3)

情况二、malloc大于128k的内存,使用mmap分配内存,在堆和栈之间找一块空闲内存分配(对应独立内存,而且初始化为0),如下图:

图(4) 图(5)图(6)

4、进程调用C=malloc(200K)以后,内存空间如图4:

默认情况下,malloc函数分配内存,如果请求内存大于128K(可由M_MMAP_THRESHOLD选项调节),那就不是去推_edata指针了,而是利用mmap系统调用,从堆和栈的中间分配一块虚拟内存。

这样子做主要是因为:

brk分配的内存需要等到高地址内存释放以后才能释放(例如,在B释放之前,A是不可能释放的,这就是内存碎片产生的原因,什么时候紧缩看下面),而mmap分配的内存可以单独释放。

当然,还有其它的好处,也有坏处,再具体下去,有兴趣的同学可以去看glibc里面malloc的代码了。

5 、进程调用D=malloc(100K)以后,内存空间如图5;

6 、进程调用free(C)以后,C对应的虚拟内存和物理内存一起释放。

图(7) 图(8)图(9)

7、进程调用free(B)以后,如图7所示:

B对应的虚拟内存和物理内存都没有释放,因为只有一个_edata指针,如果往回推,那么D这块内存怎么办呢?

当然,B这块内存,是可以重用的,如果这个时候再来一个40K的请求,那么malloc很可能就把B这块内存返回回去了。

8、进程调用free(D)以后,如图8所示:

B和D连接起来,变成一块140K的空闲内存。

9、默认情况下:

当最高地址空间的空闲内存超过128K(可由M_TRIM_THRESHOLD选项调节)时,执行内存紧缩操作(trim)。在上一个步骤free的时候,发现最高地址空闲内存超过128K,于是内存紧缩,变成图9所示。


头文件

/usr/include/malloc.h

int mallopt (int __param, int __val);

参数 __param的取值范围:-8<=param<=-1 || 1<=param<=4 如下:

#define M_TRIM_THRESHOLD    -1
#define M_TOP_PAD           -2
#define M_MMAP_THRESHOLD    -3
#define M_MMAP_MAX          -4
#define M_CHECK_ACTION      -5
#define M_PERTURB           -6
#define M_ARENA_TEST        -7
#define M_ARENA_MAX         -8

#ifndef M_MXFAST
# define M_MXFAST  1    /* maximum request size for "fastbins" */
#endif
#ifndef M_NLBLKS
# define M_NLBLKS  2    /* UNUSED in this malloc */
#endif
#ifndef M_GRAIN
# define M_GRAIN   3    /* UNUSED in this malloc */
#endif
#ifndef M_KEEP
# define M_KEEP    4    /* UNUSED in this malloc */
#endif

参数 __value的取值: https://www.linuxjournal.com/article/6390

Table 1. mallopt() Parameters Mapped to Environment Variables

mallopt() param选择 bash环境变量 value默认推荐值 备注
M_TRIM_THRESHOLD MALLOC_TRIM_THRESHOLD_ 128KB -1U disables
M_TOP_PAD MALLOC_TOP_PAD_ 0
M_MMAP_THRESHOLD MALLOC_MMAP_THRESHOLD_ 128KB 0 disables
M_MMAP_MAX MALLOC_MMAP_MAX_ 64 0 disables

函数返回值1表示成功,0表示失败并修改全局变量errno;

相关文章

网友评论

      本文标题:头文件malloc.h:函数 mallopt()的选项

      本文链接:https://www.haomeiwen.com/subject/nticqhtx.html