博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ptmalloc——smallbin/largebin/unsortedbin
阅读量:5744 次
发布时间:2019-06-18

本文共 9846 字,大约阅读时间需要 32 分钟。

hot3.png

中讲到了ptmalloc用链表的方式将相似大小的chunk链接起来,这些链表称为bin。除了fastbin,ptmalloc还包括unsorted bin,small bins,large bins。

small bins中存放固定大小的chunk,两个相邻的small bin中的chunk大小相差16字节(对于64位系统而言),同一链表中的chunk按照最近使用顺序进行排序,最后释放的chunk被链接到链表的头部,而申请chunk时从链表的尾部开始,small bin中的chunk在内存中大概如下图所示:

相对于small bin中的chunk都是固定大小,large bin链表中的chunk的大小都是在一定范围内的。因此这些chunk按照大小进行排序,相对较大的chunk在链表的头部,相对较小的chunk则在链表的尾部。除了正常的双向链表指针外,还有额外的两个指针,用于双向链接不同长度的chunk。large bin中的chunk在内存中大概如下图所示:

注:A,B,C三个chunk的长度具有相同的大小;同样D,E,F具有相同的大小;G,H,I具有相同的大小,A/B/C chunk的长度最大,其次是D/E/F chunk的长度,最小的是G/H/I。

unsorted bin顾名思义,即大小未排序的链表,不在fastbin范围内的chunk,被释放后,ptmalloc首先将其放到unsorted bin中;而申请chunk时,首先从unsorted bin中查找相同长度的chunk,同时将unsorted bin中的chunk按照其大小分别放到不同的small bin和large bin中。

下面程序验证small bin的链表结构,以及分配的顺序:

void test_smallbin(){    char * p1[6];    char * p2[6];    int i = 0;    for( i = 0; i < 6; i++ ) {        p1[i] = (char*)malloc(200);        char * pChunkAddr = p1[i] - 16;        printf("[%d] mem: %p chunk: %p\n", i, p1[i], pChunkAddr);    }    for( i = 0; i < 6; i++ ) {        p2[i] = (char*)malloc(400);        char * pChunkAddr = p2[i] - 16;        printf("[%d] mem: %p chunk: %p\n", i, p2[i], pChunkAddr);    }    for( i = 0; i < 6; i += 2 ) {        if( NULL != p1[i] ) {            free( p1[i] );        }        if( NULL != p2[i] ) {            free( p2[i] );        }    }    printf("\nin unsorted bin:\n");    for( i = 0; i < 6; i+= 2 ) {        if( NULL != p1[i] ) {            size_t next = *((size_t*)p1[i]);            size_t forward = *((size_t*)(p1[i]+8));            printf("chunk: %p next chunk-> %p forward chunk-> %p\n", (p1[i]-16), next, forward);        }        if( NULL != p2[i] ) {            size_t next = *((size_t*)p2[i]);            size_t forward = *((size_t*)(p2[i]+8));            printf("chunk: %p next chunk-> %p forward chunk-> %p\n", (p2[i]-16), next, forward);        }    }    char * tmp1 = (char*)malloc(512);    printf("\nin small bins:\n");    for( i = 0; i < 6; i+= 2 ) {        if( NULL != p1[i] ) {            size_t next = *((size_t*)p1[i]);            size_t forward = *((size_t*)(p1[i]+8));            printf("chunk: %p next chunk-> %p forward chunk-> %p\n", (p1[i]-16), next, forward);        }    }    for( i = 0; i < 6; i+= 2 ) {        if( NULL != p2[i] ) {            size_t next = *((size_t*)p2[i]);            size_t forward = *((size_t*)(p2[i]+8));            printf("chunk: %p next chunk-> %p forward chunk-> %p\n", (p2[i]-16), next, forward);        }    }    char * tmp = (char*)malloc(400);    printf("tmp mem: %p chunk: %p\n", tmp, (tmp-16));    // 后续资源清理}

程序运行结果为:

[0] mem: 0x188f010 chunk: 0x188f000[1] mem: 0x188f0e0 chunk: 0x188f0d0[2] mem: 0x188f1b0 chunk: 0x188f1a0[3] mem: 0x188f280 chunk: 0x188f270[4] mem: 0x188f350 chunk: 0x188f340[5] mem: 0x188f420 chunk: 0x188f410[0] mem: 0x188f4f0 chunk: 0x188f4e0[1] mem: 0x188f690 chunk: 0x188f680[2] mem: 0x188f830 chunk: 0x188f820[3] mem: 0x188f9d0 chunk: 0x188f9c0[4] mem: 0x188fb70 chunk: 0x188fb60[5] mem: 0x188fd10 chunk: 0x188fd00in unsort bin:chunk: 0x188f000 next chunk-> 0x380678e178 forward chunk-> 0x188f4e0chunk: 0x188f4e0 next chunk-> 0x188f000 forward chunk-> 0x188f1a0chunk: 0x188f1a0 next chunk-> 0x188f4e0 forward chunk-> 0x188f820chunk: 0x188f820 next chunk-> 0x188f1a0 forward chunk-> 0x188f340chunk: 0x188f340 next chunk-> 0x188f820 forward chunk-> 0x188fb60chunk: 0x188fb60 next chunk-> 0x188f340 forward chunk-> 0x380678e178in small bins:chunk: 0x188f000 next chunk-> 0x380678e238 forward chunk-> 0x188f1a0chunk: 0x188f1a0 next chunk-> 0x188f000 forward chunk-> 0x188f340chunk: 0x188f340 next chunk-> 0x188f1a0 forward chunk-> 0x380678e238chunk: 0x188f4e0 next chunk-> 0x380678e308 forward chunk-> 0x188f820chunk: 0x188f820 next chunk-> 0x188f4e0 forward chunk-> 0x188fb60chunk: 0x188fb60 next chunk-> 0x188f820 forward chunk-> 0x380678e308tmp mem: 0x188f4f0 chunk: 0x188f4e0

下面程序验证large bin的链表结构

void test_largebin(){    char * p1[6];    char * p2[6];    char * p3[6];    int i = 0;    for( i = 0; i < 6; i++ ) {        p1[i] = (char*)malloc(1025);        char * pChunkAddr = p1[i] - 16;        printf("[%d] mem: %p chunk: %p\n", i, p1[i], pChunkAddr);    }    for( i = 0; i < 6; i++ ) {        p2[i] = (char*)malloc(1058);        char * pChunkAddr = p2[i] - 16;        printf("[%d] mem: %p chunk: %p\n", i, p2[i], pChunkAddr);    }    for( i = 0; i < 6; i++ ) {        p3[i] = (char*)malloc(1041);        char * pChunkAddr = p3[i] - 16;        printf("[%d] mem: %p chunk: %p\n", i, p3[i], pChunkAddr);    }    for( i = 0; i < 6; i += 2 ) {        if( NULL != p1[i] ) {            free( p1[i] );        }        if( NULL != p2[i] ) {            free( p2[i] );        }        if( NULL != p3[i] ) {            free( p3[i] );        }    }    printf("\nin unsort bins:\n");    for( i = 0; i < 6; i += 2 ) {        if( NULL != p1[i] ) {            size_t next = *((size_t*)p1[i]);            size_t forward = *((size_t*)(p1[i]+8));            printf("chunk: %p next chunk-> %p forward chunk-> %p\n", (p1[i]-16), next, forward);        }        if( NULL != p2[i] ) {            size_t next = *((size_t*)p2[i]);            size_t forward = *((size_t*)(p2[i]+8));            printf("chunk: %p next chunk-> %p forward chunk-> %p\n", (p2[i]-16), next, forward);        }        if( NULL != p3[i] ) {            size_t next = *((size_t*)p3[i]);            size_t forward = *((size_t*)(p3[i]+8));            printf("chunk: %p next chunk-> %p forward chunk-> %p\n", (p3[i]-16), next, forward);        }    }    char * tmp1 = (char*)malloc(1800);    printf("\nin large bins:\n");    for( i = 0; i < 6; i += 2 ) {        if( NULL != p2[i] ) {            size_t nChunkSize = *((size_t*)(p2[i]-8)) & (~(0x7));            size_t next = *((size_t*)p2[i]);            size_t forward = *((size_t*)(p2[i]+8));            size_t nextSizeChunk = *((size_t*)(p2[i]+16));            size_t forwardSizeChunk = *((size_t*)(p2[i]+24));            printf("chunk: %p chunk size: %d\n", (p2[i]-16), nChunkSize);            printf("next chunk-> %p forward chunk-> %p\n", next, forward);            printf("next size chunk-> %p forward size chunk-> %p", nextSizeChunk, forwardSizeChunk);        }    }    for( i = 0; i < 6; i += 2 ) {        if( NULL != p3[i] ) {            size_t nChunkSize = *((size_t*)(p3[i]-8)) & (~(0x7));            size_t next = *((size_t*)p3[i]);            size_t forward = *((size_t*)(p3[i]+8));            size_t nextSizeChunk = *((size_t*)(p3[i]+16));            size_t forwardSizeChunk = *((size_t*)(p3[i]+24));            printf("chunk: %p chunk size: %d\n", (p3[i]-16), nChunkSize);            printf("next chunk-> %p forward chunk-> %p\n", next, forward);            printf("next size chunk-> %p forward size chunk-> %p", nextSizeChunk, forwardSizeChunk);        }    }    for( i = 0; i < 6; i += 2 ) {        if( NULL != p1[i] ) {            size_t nChunkSize = *((size_t*)(p1[i]-8)) & (~(0x7));            size_t next = *((size_t*)p1[i]);            size_t forward = *((size_t*)(p1[i]+8));            size_t nextSizeChunk = *((size_t*)(p1[i]+16));            size_t forwardSizeChunk = *((size_t*)(p1[i]+24));            printf("chunk: %p chunk size: %d\n", (p1[i]-16), nChunkSize);            printf("next chunk-> %p forward chunk-> %p\n", next, forward);            printf("next size chunk-> %p forward size chunk-> %p", nextSizeChunk, forwardSizeChunk);        }    }}

程序运行结果为:

[0] mem: 0x22dc010 chunk: 0x22dc000[1] mem: 0x22dc420 chunk: 0x22dc410[2] mem: 0x22dc830 chunk: 0x22dc820[3] mem: 0x22dcc40 chunk: 0x22dcc30[4] mem: 0x22dd050 chunk: 0x22dd040[5] mem: 0x22dd460 chunk: 0x22dd450[0] mem: 0x22dd870 chunk: 0x22dd860[1] mem: 0x22ddca0 chunk: 0x22ddc90[2] mem: 0x22de0d0 chunk: 0x22de0c0[3] mem: 0x22de500 chunk: 0x22de4f0[4] mem: 0x22de930 chunk: 0x22de920[5] mem: 0x22ded60 chunk: 0x22ded50[0] mem: 0x22df190 chunk: 0x22df180[1] mem: 0x22df5b0 chunk: 0x22df5a0[2] mem: 0x22df9d0 chunk: 0x22df9c0[3] mem: 0x22dfdf0 chunk: 0x22dfde0[4] mem: 0x22e0210 chunk: 0x22e0200[5] mem: 0x22e0630 chunk: 0x22e0620in unsort bins:chunk: 0x22dc000 next chunk-> 0x380678e178 forward chunk-> 0x22dd860chunk: 0x22dd860 next chunk-> 0x22dc000 forward chunk-> 0x22df180chunk: 0x22df180 next chunk-> 0x22dd860 forward chunk-> 0x22dc820chunk: 0x22dc820 next chunk-> 0x22df180 forward chunk-> 0x22de0c0chunk: 0x22de0c0 next chunk-> 0x22dc820 forward chunk-> 0x22df9c0chunk: 0x22df9c0 next chunk-> 0x22de0c0 forward chunk-> 0x22dd040chunk: 0x22dd040 next chunk-> 0x22df9c0 forward chunk-> 0x22de920chunk: 0x22de920 next chunk-> 0x22dd040 forward chunk-> 0x22e0200chunk: 0x22e0200 next chunk-> 0x22de920 forward chunk-> 0x380678e178in large bins:chunk: 0x22dc000 chunk size:1040next chunk-> 0x22dd040 forward chunk-> 0x22df9c0next large chunk-> 0x22dd860 next small chunk-> 0x22df180chunk: 0x22dc820 chunk size:1040next chunk-> 0x380678e568 forward chunk-> 0x22dd040next large chunk-> (nil) next small chunk-> (nil)chunk: 0x22dd040 chunk size:1040next chunk-> 0x22dc820 forward chunk-> 0x22dc000next large chunk-> (nil) next small chunk-> (nil)chunk: 0x22dd860 chunk size:1072next chunk-> 0x22de920 forward chunk-> 0x380678e568next large chunk-> 0x22df180 next small chunk-> 0x22dc000chunk: 0x22de0c0 chunk size:1072next chunk-> 0x22df180 forward chunk-> 0x22de920next large chunk-> (nil) next small chunk-> (nil)chunk: 0x22de920 chunk size:1072next chunk-> 0x22de0c0 forward chunk-> 0x22dd860next large chunk-> (nil) next small chunk-> (nil)chunk: 0x22df180 chunk size:1056next chunk-> 0x22e0200 forward chunk-> 0x22de0c0next large chunk-> 0x22dc000 next small chunk-> 0x22dd860chunk: 0x22df9c0 chunk size:1056next chunk-> 0x22dc000 forward chunk-> 0x22e0200next large chunk-> (nil) next small chunk-> (nil)chunk: 0x22e0200 chunk size:1056next chunk-> 0x22df9c0 forward chunk-> 0x22df180next large chunk-> (nil) next small chunk-> (nil)

 

转载于:https://my.oschina.net/hncscwc/blog/994703

你可能感兴趣的文章
Erlang简史(翻译)
查看>>
深入实践Spring Boot2.4.2 节点和关系实体建模
查看>>
10个巨大的科学难题需要大数据解决方案
查看>>
Setting Up a Kerberos server (with Debian/Ubuntu)
查看>>
用 ThreadLocal 管理用户session
查看>>
setprecision后是要四舍五入吗?
查看>>
shiro初步 shiro授权
查看>>
上云就是这么简单——阿里云10分钟快速入门
查看>>
MFC多线程的创建,包括工作线程和用户界面线程
查看>>
我的友情链接
查看>>
FreeNAS8 ISCSI target & initiator for linux/windows
查看>>
cvs文件提交冲突解决方案
查看>>
PostgreSQL数据库集群初始化
查看>>
++重载
查看>>
Rainbond 5.0.4版本发布-做最好用的云应用操作系统
查看>>
nodejs 完成mqtt服务端
查看>>
在ASP.NET MVC 中获取当前URL、controller、action
查看>>
Spring IoC容器初的初始化过程
查看>>
sql server 触发器
查看>>
[工具]前端自动化工具grunt+bower+yoman
查看>>