ptmalloc
来源:互联网 发布:哪里有网络水军可以请 编辑:程序博客网 时间:2024/05/16 04:52
ptmalloc - 第一次申请小内存
glibc中malloc的代码包括了对线程同步,平台兼容性等问题的处理,但是本系列文章主要的研究对象ptmalloc。所以提供的代码都是经过简化,部分宏也会展开,能够说清楚ptmalloc的运行流程就可以了。
要点
- 用例
- 第一次申请小内存
用例
int main(void){ char *mem = malloc(10); free(mem); return -1;}
第一次申请小内存
通过gdb调试,我们可以看到,第一个进入的函数是__libc_malloc
void *__libc_malloc(size_t bytes){ mstate ar_ptr; void *victim; void *(*hook) (size_t, const void *) = __malloc_hook; if (hook != NULL) { hook(bytes, 0); } ar_ptr = thread_arena; victim = _int_malloc(ar_ptr, bytes); return victim;}
查看__malloc_hook的初始赋值
__malloc_hook = malloc_hook_ini;
继续跟踪malloc_hook_ini
static void *malloc_hook_ini (size_t sz, const void *caller){ __malloc_hook = NULL; ptmalloc_init (); return __libc_malloc (sz);}static voidptmalloc_init (void){ if (__malloc_initialized >= 0) return; __malloc_initialized = 0; thread_arena = &main_arena;}
从malloc_hook_ini 可以看到,最后调用的就是__libc_malloc,往回看,因为hook被设置为NULL,所以接下来调用的就是_int_malloc,先放些宏出来,如果不想看可以直接跳过去看简化的_int_malloc代码
#define SIZE_SZ sizeof(size_t)/* * 如果size_t的大小是8,那么MALLOC_ALIGN_MASK就是8 * 2 -1 * 2进制是01111111,代码中的作用就是通过位运算将数值16bit对齐 */#define MALLOC_ALIGN_MASK (SIZE_SZ * 2 - 1)/* * 最小块大小,每次申请返回的内存都是经过大小调整后加上MIN_CHUNK_SIZE * 这样,每次返回的内存前面就包含了两个size_t的数值 * mchunk_size和mchunk_prev_size * x86_64下,sizeof(size_t) = 8,那么MIN_CHUNK_SIZE = 16 */#define MIN_CHUNK_SIZE \ (offsetof(struct malloc_chunk, fd_nextsize))/* * (16 + 15) & ~15 = 16 */#define MINSIZE \ ((MIN_CHUNK_SIZE + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)/* * 注意代码中的是-2,-2 * MINSIZE然后再强转后就是一个很大的数值了 */#define REQUEST_OUT_OF_RANGE(req) \ ((unsigned long) (req) >= (unsigned long) (INTERNAL_SIZE_T) (-2 * MINSIZE))#define request2size(req) \ (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \ MINSIZE : \ /* (req + 8 + 15) & ~15 */ ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)#define checked_request2size(req, sz) \ if (REQUEST_OUT_OF_RANGE (req)) { \ __set_errno (ENOMEM); \ return 0; \ } \ (sz) = request2size (req);
当size是10的话,参数nb的值就是32,想知道怎么算出来的直接看以上贴出来的宏就可以了
struct malloc_chunk { INTERNAL_SIZE_T mchunk_prev_size; INTERNAL_SIZE_T mchunk_size; struct malloc_chunk* fd; struct malloc_chunk* bk; struct malloc_chunk* fd_nextsize; struct malloc_chunk* bk_nextsize;};struct mstate { ... int flags; mchunkptr top; mchunkptr last_remainder; mchunkptr bins[254]; ...};typedef struct malloc_chunk *mbinptr;typedef struct malloc_state *mstate;#define bin_at(m, i) \ (mbinptr) (((char *) &((m)->bins[((i) - 1) * 2])) - MIN_CHUNK_SIZE static void malloc_init_state(mstate av){ int i; mbinptr bin; /* Establish circular links for normal bins */ for (i = 1; i < NBINS; ++i) { bin = bin_at (av, i); bin->fd = bin->bk = bin; }#if MORECORE_CONTIGUOUS if (av != &main_arena)#endif av->flags |= NONCONTIGUOUS_BIT; if (av == &main_arena) global_max_fast = 128; av->flags |= FASTCHUNKS_BIT; av->top = bin_at(av, 1);}static void *_int_malloc (mstate av, size_t bytes){ int32_t nb = 32; malloc_init_state(av); return sysmalloc(nb, av);}
代码是很多,不过第一次申请也准备到达尽头了,最后一个函数sysmalloc
static struct malloc_par mp_ ={ ... .top_pad = 0x20000, ...};#define PREV_INUSE 0x1static void *sysmalloc(size_t nb, mstate av){ size_t pagesize = 4096; /* * 可以看出第一次申请内存的时候 * ptmalloc会申请一块很大的内存 */ size_t size = nb + mp_.top_pad + MIN_SIZE; char *brk; /* size必须要pagesize的倍数 */ size = (size + pagesize - 1) & -pagesize; if (size > 0) { brk = sbrk(size); } if (brk != NULL) { av->system_mem += size; } if ((unsigned long) av->system_mem > (unsigned long) (av->max_system_mem)) av->max_system_mem = av->system_mem; size_t remainder_size; mchunkptr p = av->top, remainder; if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE)) { remainder_size = size - nb; remainder = p + nb; av->top = remainder; /* * 要记得nb永远是16的倍数,所以数值的第一字节都是0xX0000 */ p->mchunk_size = nb | PREV_INUSE; remainder->mchunk_size = remainder_size | PREV_INUSE return p + MIN_CHUNK_SIZE; }}
本来的代码有更多的分支,处理,判断,我上面的代码都简化了很多,如果想感受ptmalloc的代码难看性,自行下载吧,下一章有可能是第一次申请大内存或者释放小内存,看心情吧。
完结撒花
阅读全文
0 0
- ptmalloc
- ptmalloc
- ptmalloc
- ptmalloc
- ptmalloc
- ptmalloc
- ptmalloc
- ptmalloc
- ptmalloc
- ptmalloc
- ptmalloc
- ptmalloc
- PTmalloc hacking
- ptmalloc代码浅析1
- ptmalloc代码浅析3
- ptmalloc分配器的分析
- ptmalloc源码阅读-malloc_chunk
- ptmalloc的分配顺序
- Aspera从NCBI下载基因组数据
- 数据结构之红黑树(二)——插入操作
- android控件04---ProgressBar
- jsp tomcat apache web.xml编译错误问题解决
- JDBC链接MySql数据库的测试Demo
- ptmalloc
- linux下如何实现mysql数据库每天自动备份定时备份
- ruby使用国内的镜像操作方法
- 在visual studio2015中配置OpenCV的环境一劳永逸的方法
- P1108 低价购买dp
- Find The Multiple
- 数据结构之红黑树(三)——删除操作
- Java排序算法实现及优劣分析
- 关于table固定列宽度的解决方案