分类: LINUX
2011-10-08 15:56:23
下面我们开始分析三个malloc函数分别是DevMemSysAllocator,MmapSysAllocator,以及SbrkSysAllocator(./src/system-alloc.cc)。
首先分析SbrkSysAllocator(./src/system-alloc.cc)
void* SbrkSysAllocator::Alloc(size_t size, size_t *actual_size,
size_t alignment) {
#ifndef HAVE_SBRK
failed_ = true;
return NULL;
#else
// Check if we should use sbrk allocation.
// FLAGS_malloc_skip_sbrk starts out as false (its uninitialized
// state) and eventually gets initialized to the specified value. Note
// that this code runs for a while before the flags are initialized.
// That means that even if this flag is set to true, some (initial)
// memory will be allocated with sbrk before the flag takes effect.
if (FLAGS_malloc_skip_sbrk) {
return NULL;
}
//首先判断内存的分配是否采用sbrk,如果FLAGS_malloc_skip_sbrk设置为true那么代表着不适用sbrk,则直接返回NULL,代表分配失败。
// sbrk will release memory if passed a negative number, so we do
// a strict check here
if (static_cast
//由于sbrk可以通过传入负值动态缩减heap顶部,因此在分配函数中把这种情况先排除。
// This doesn't overflow because TCMalloc_SystemAlloc has already
// tested for overflow at the alignment boundary.
size = ((size + alignment - 1) / alignment) * alignment;
//通过alignment对齐,将非对齐的size转换为对齐
// "actual_size" indicates that the bytes from the returned pointer
// p up to and including (p + actual_size - 1) have been allocated.
if (actual_size) {
*actual_size = size;
}
// Check that we we're not asking for so much more memory that we'd
// wrap around the end of the virtual address space. (This seems
// like something sbrk() should check for us, and indeed opensolaris
// does, but glibc does not:
//
// ~checkout~/libc/misc/sbrk.c?rev=1.1.2.1&content-type=text/plain&cvsroot=glibc
// Without this check, sbrk may succeed when it ought to fail.)
if (reinterpret_cast
failed_ = true;
return NULL;
}//判断我们申请的size有没有超过进程空间能够提供的最大值
void* result = sbrk(size);
if (result == reinterpret_cast
failed_ = true;
return NULL;
}
//利用sbrk申请size大小的空间
// Is it aligned?
uintptr_t ptr = reinterpret_cast
if ((ptr & (alignment-1)) == 0) return result;
//如果申请成功,那么判断是否符合对齐要求,如果对齐,那么返回结果
// Try to get more memory for alignment
size_t extra = alignment - (ptr & (alignment-1));
//如果没有对齐,那么判断还缺少多少size可以对齐,
void* r2 = sbrk(extra);
//申请需要的size进行对齐
if (reinterpret_cast
// Contiguous with previous result
return reinterpret_cast
//符合对齐要求,那么返回结果
}
// Give up and ask for "size + alignment - 1" bytes so
// that we can find an aligned region within it.
result = sbrk(size + alignment - 1);//否者将不管对齐与否,申请一个比size大的空间,至少保证在这个空间内可以找到一块对齐的空间,这里面应该分为两种情况,第一种情况是以上分配都是失败的,第二种情况是分配没有失败,只是没有找到相应的对齐
if (result == reinterpret_cast
failed_ = true;
return NULL;
}
ptr = reinterpret_cast
if ((ptr & (alignment-1)) != 0) {
ptr += alignment - (ptr & (alignment-1));
//保证ptr顶部对齐
}
return reinterpret_cast
#endif // HAVE_SBRK
}