- 浏览: 187282 次
- 性别:
- 来自: 杭州
最新评论
-
hxz_qlh:
“M_MMAP_MAX用于设置进程中用mmap分配的内存块的最 ...
Glibc内存管理--ptmalloc2源代码分析(九) -
boyhailong:
总结的很好,顶
程序编码与调试 -
zdl1016:
关于mmap内存的增长方向,貌似应该是向下增长的,我连续申请三 ...
Glibc内存管理--ptmalloc2源代码分析(三十四) -
xly931:
请教大神,其实我有点疑惑的是为什么同一个库有映射到进程空间中, ...
linux进程内存布局 -
hengyunabc:
额,为什么在slideshare不能下载,在这里可以下载?
Glibc内存管理--ptmalloc2源代码分析(三十四)
文章列表
5.5.2 ptmalloc_init()函数
ptmalloc_init()
函数比较长,将分段对这个函数做介绍。
static void
ptmalloc_init (void)
{
#if __STD_C
const char* s;
#else
char* s;
#endif
int secure = 0;
if(__malloc_initialized >= 0) return;
__malloc_initialized = 0;
首先检查全局变量
__malloc_initialized
...
5.5 Ptmalloc初始化
Ptmalloc的初始化发生在进程的第一个内存分配请求,当
ptmalloc
的初始化一般都在用户的第一次调用
malloc()
或
remalloc()
之前,因为操作系统和
Glibc
库为进程的初始化做了不少工作,在用户分配内存以前,
Glibc
已经分配了多次内存。
在
ptmalloc
中
malloc()
函数的实际接口函数为
public_mALLOc()
,这个函数最开始会执行如下的一段代码:
__malloc_ptr_t (*hook) (size_t, __const __malloc ...
5.4 配置选项
Ptmalloc的配置选项不多,在
3.2.6
节已经做过概要描述,这里给出
mallopt()
函数的实现:
#if __STD_C
int mALLOPt(int param_number, int value)
#else
int mALLOPt(param_number, value) int param_number; int value;
#endif
{
mstate av = &main_arena;
int res = 1;
if(__malloc_initialized < 0)
...
5.3
核心结构体分析
每个分配区是
struct
malloc_state
的一个实例,
ptmalloc
使用
malloc_state
来管理分配区,而参数管理使用
struct malloc_par
,全局拥有一个唯一的
malloc_par
实例。
5.3.1
malloc_state
stuct malloc_state
的定义如下:
struct malloc_state {
/* Serialize access. */
mutex_t mu ...
5.2.3
Unsorted bin
Unsorted
bin
可以看作是
small bins
和
large bins
的
cache
,只有一个
unsorted bin
,以双向链表管理空闲
chunk
,空闲
chunk
不排序,所有的
chunk
在回收时都要先放到
unsorted bin
中,分配时,如果在
unsorted bin
中没有合适的
chunk
,就会把
unsorted bin
中的所有
chunk
分别加入到所属的
bin
中,然后再在
bin
中分配 ...
.2.2
Large bins
在
SIZE_SZ
为
4B
的平台上,大于等于
512B
的空闲
chunk
,或者,在
SIZE_SZ
为
8B
的平台上,大小大于等于
1024B
的空闲
chunk
,由
sorted bins
管理。
Large bins
一共包括
63
个
bin
,每个
bin
中的
chunk
大小不是一个固定公差的等差数列,而是分成
...
5.2
分箱式内存管理
对于空闲的
chunk
,
ptmalloc
采用分箱式内存管理方式,根据空闲
chunk
的大小和处于的状态将其放在四个不同的
bin
中,这四个空闲
chunk
的容器包括
fast bins
,
unsorted bin
,
small bins
和
large bins
。
Fast bins
是小内存块的高速缓存,当一些大小小于
64
字节的
chunk
被回收时,首先会放入
fast bins
中,在分配小内存时,首先会查看
fast bins
中是否有合适的内存块,如果存 ...
5.
源代码分析
分主要对源代码实现技巧的细节做分析,希望能进一步理解
ptmalloc
的实现,做到终极无惑。主要分析的文件包括
arena.c
和
malloc.c
,这两个文件包括了
ptmalloc
的核心实现,其中
arena.c
主要是对多线程支持的实现,
malloc.c
定义了公用的
malloc()
,
free()
等函数,实现了基于分配区的内存管理算法。本部分不会从头到尾分析
arena.c
和
malloc.c
整个文件,而是根据
ptmalloc
的实现原理,分成几个模块分别介绍,主要分析了
mal ...
4. 问题分析及解决
通过前面几节对ptmalloc实现的粗略分析,尝试去分析和解决我们遇到的问题,我们系统遇到的问题是glibc内存暴增,现象是程序已经把内存返回给了Glibc库,但Glibc库却没有把内存归还给操作系统,最终导致系统内存耗尽,程序因为OOM被系统杀掉。
请参考3.2.2节对ptmalloc的设计假设与3.2.7节对ptmalloc的使用注意事项,原因有如下几点:
在64
3.2.7 使用注意事项
为了避免Glibc内存暴增,使用时需要注意以下几点:
后分配的内存先释放,因为ptmalloc收缩内存是从top chunk开始,如果与top chunk相邻的chunk不能释放,top chunk以下的chunk都无法释放。
Ptmalloc不适合用于管理长生命周期的内存,特别是持续不定期分配和释放长生命周期的内存,这将导致ptmalloc内存暴增。如果要用ptmalloc分配长周期内存,在32位系统上,分配的内存块最好大于1MB
3.2.6 配置选项概述
Ptmalloc主要提供以下几个配置选项用于调优,这些选项可以通过mallopt()进行设置:
1. M_MXFAST
M_MXFAST用于设置fast bins中保存的chunk的最大大小,默认值为64B,fast bins中保存的chunk在一段时间内不会被合并,分配小对象时可以首先查找fast bins,如果fast bins找到了所需大小的chunk
3.2.5 内存回收概述
free() 函数接受一个指向分配区域的指针作为参数,释放该指针所指向的chunk。而具体的释放方法则看该chunk所处的位置和该chunk的大小。free()函数的工作步骤如下:
free()函数同样首先需要获取分配区的锁,来保证线程安全。
判断传入的指针是否为0,如果为0,则什么都不做,直接return。否则转下一步。
3.2.4 内存分配概述
分配算法概述,以32系统为例,64位系统类似。
小于等于64字节:用pool算法分配。
64到512字节之间:在最佳匹配算法分配和pool算法分配中取一种合适的。
大于等于512字节:用最佳匹配算法分配。
大于等于mmap分配阈值(默认值128KB)
3.2.3.4 sbrk与mmap
从进程的内存布局可知,.bss 段之上的这块分配给用户程序的空间被称为heap (堆)。start_brk指向heap的开始,而brk指向heap的顶部。可以使用系统调用brk()和sbrk()来增加标识heap顶部的brk值,从而线性的增加分配给用户的heap空间。在使malloc之前,brk的值等于
3.2.3内存管理数据结构概述
3.2.3.1 Main_arena与non_main_arena
在Doug Lea实现的内存分配器中只有一个主分配区(main arena),每次分配内存都必须对主分配区加锁,分配完成后释放锁,在SMP多线程环境下,对主分配区的锁的争用很 ...