glibc下malloc的理解
来源:互联网 发布:oracle数据库基础教程 编辑:程序博客网 时间:2024/05/21 19:46
0.1 简介
在linux中常见的malloc是glibc的malloc,经对glibc上malloc修改有适用于linux多线程的malloc
即dlmalloc
,还有一个ptmalloc2
这两者有区别,其区别在于:
dlmalloc
在子线程和父线程同时调用malloc时会有竞争,且只会有一个能够从heap中分配到空间。并且freelist data structure
是被众进程共享的。
ptmalloc2
可以确保不有这种竞争,而且freelist
是各自进程独享自己的一个结构体。ptmalloc是per thread malloc
之意。
1.malloc用例
/* Per thread arena example. */#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>#include <sys/types.h>void* threadFunc(void* arg) { printf("Before malloc in thread 1\n"); getchar(); char* addr = (char*) malloc(1000); printf("After malloc and before free in thread 1\n"); getchar(); free(addr); printf("After free in thread 1\n"); getchar();}int main() { pthread_t t1; void* s; int ret; char* addr; printf("Welcome to per thread arena example::%d\n",getpid()); printf("Before malloc in main thread\n"); getchar(); addr = (char*) malloc(1000); printf("After malloc and before free in main thread\n"); getchar(); free(addr); printf("After free in main thread\n"); getchar(); ret = pthread_create(&t1, NULL, threadFunc, NULL); if(ret) { printf("Thread creation error\n"); return -1; } ret = pthread_join(t1, &s); if(ret) { printf("Thread join error\n"); return -1; } return 0;}
情景1
main thread
malloc之前
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/mthread$ ./mthread Welcome to per thread arena example::6501Before malloc in main thread...sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/mthread$ cat /proc/6501/maps08048000-08049000 r-xp 00000000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread08049000-0804a000 r--p 00000000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread0804a000-0804b000 rw-p 00001000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthreadb7e05000-b7e07000 rw-p 00000000 00:00 0
再未用malloc时,尚未分配heap
情景2
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/mthread$ ./mthread Welcome to per thread arena example::6501Before malloc in main threadAfter malloc and before free in main thread...sploitfun@sploitfun-VirtualBox:~/lsploits/hof/ptmalloc.ppt/mthread$ cat /proc/6501/maps08048000-08049000 r-xp 00000000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread08049000-0804a000 r--p 00000000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread0804a000-0804b000 rw-p 00001000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread0804b000-0806c000 rw-p 00000000 00:00 0 [heap]b7e05000-b7e07000 rw-p 00000000 00:00 0
使用malloc后即在
0x084b000~0x086c000
开辟一个heap。虽然源码中要分配1000字节,但这里分配了132k,这是预先分配出一块内存专门给malloc用,这样以后再有malloc就直接从这块区域中在分配了,其中这块区域以brk来活动地分配heap的界限。
addr = (char*) malloc(1000);
情景3
当运行了free
之后,heap区并未释放给os,这是一种策略,当再次malloc时再从这里分配,当若干时间后,才会降低brk
值来减小top层的无用的chunk。
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/mthread$ ./mthread Welcome to per thread arena example::6501Before malloc in main threadAfter malloc and before free in main threadAfter free in main thread...sploitfun@sploitfun-VirtualBox:~/lsploits/hof/ptmalloc.ppt/mthread$ cat /proc/6501/maps08048000-08049000 r-xp 00000000 08:01 539625 home/sploitfun/ptmalloc.ppt/mthread/mthread08049000-0804a000 r--p 00000000 08:01 539625 home/sploitfun/ptmalloc.ppt/mthread/mthread0804a000-0804b000 rw-p 00001000 08:01 539625 home/sploitfun/ptmalloc.ppt/mthread/mthread0804b000-0806c000 rw-p 00000000 00:00 0 [heap]b7e05000-b7e07000 rw-p 00000000 00:00 0
情景4
当运行到thread1子线程时,子线程会分配其stack
,但此时尚未分配子线程的heap
。
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/mthread$ ./mthread Welcome to per thread arena example::6501Before malloc in main threadAfter malloc and before free in main threadAfter free in main threadBefore malloc in thread 1...sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/mthread$ cat /proc/6501/maps08048000-08049000 r-xp 00000000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread08049000-0804a000 r--p 00000000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread0804a000-0804b000 rw-p 00001000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread0804b000-0806c000 rw-p 00000000 00:00 0 [heap] 具有读写权限b7604000-b7605000 ---p 00000000 00:00 0 **b7605000-b7e07000 rw-p 00000000 00:00 0 [stack:6594]**
情景5
子线程中malloc情景,子线程的heap创建用的是mmap
系统调用,而不是mainthread中用的sbrk
系统调用。当申请超过128k时会用mmap而不是sbrk,但这里只申请了1k啊(?)
(那么malloc究竟是怎么选择系统调用的呢?)
总共mmap的1M数据从0xb7500000~0xb7600000
但是只是前132k具有读写权限。可以使heap
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/mthread$ ./mthread Welcome to per thread arena example::6501Before malloc in main threadAfter malloc and before free in main threadAfter free in main threadBefore malloc in thread 1After malloc and before free in thread 1...sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/mthread$ cat /proc/6501/maps08048000-08049000 r-xp 00000000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread08049000-0804a000 r--p 00000000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread0804a000-0804b000 rw-p 00001000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread0804b000-0806c000 rw-p 00000000 00:00 0 [heap]b7500000-b7521000 rw-p 00000000 00:00 0 只有132k具有读写权限b7521000-b7600000 ---p 00000000 00:00 0 b7604000-b7605000 ---p 00000000 00:00 0 b7605000-b7e07000 rw-p 00000000 00:00 0 [stack:6594]
情景6
当子线程free时,其heap并未释放给os。
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/mthread$ ./mthread Welcome to per thread arena example::6501Before malloc in main threadAfter malloc and before free in main threadAfter free in main threadBefore malloc in thread 1After malloc and before free in thread 1After free in thread 1...sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/mthread$ cat /proc/6501/maps08048000-08049000 r-xp 00000000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread08049000-0804a000 r--p 00000000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread0804a000-0804b000 rw-p 00001000 08:01 539625 /home/sploitfun/ptmalloc.ppt/mthread/mthread0804b000-0806c000 rw-p 00000000 00:00 0 [heap]b7500000-b7521000 rw-p 00000000 00:00 0 b7521000-b7600000 ---p 00000000 00:00 0 b7604000-b7605000 ---p 00000000 00:00 0 b7605000-b7e07000 rw-p 00000000 00:00 0 [stack:6594]
2.terminology
arena
的大小:
与cpu的核数有关;
32-bit系统 : 2*cpu_core_num64-bit系统 : 8*cpu_core_num
multi-arena
多线程的共享:
假如某个app有4个线程:main thread和thread1、thread2以及thread3。跑在32bit的1核cpu上。经计算可以有2个arena。肯定是不够一一对应的,随意需要共享:
main thread 首先创建自己的arena,无竞争
thread1、thread2创建自己的arena,无竞争(??)
thread3需要竞争会从所有的arena中轮训获得lock,如果获得了,就占有执行。
否则的话需要等待lock
当main thread和thread3共享一个arena时,这两个线程就实现了共享。
数据结构
struct smem_heap_info { unsigned initialized; unsigned free_offset; unsigned heap_remaining; unsigned reserved;};struct smem_heap_info heap_info;
每一个thread arena含有multi-heaps,每一个heap都有这个heap_info
头,因为在thread arena中,每个thread最开始都仅有一个heap,当该thread有过多的malloc,超过这个初始的heap时,需要从thread arena中再找一个heap。
fine MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)struct malloc_state { binmap_t smallmap; binmap_t treemap; size_t dvsize; size_t topsize; char* least_addr; mchunkptr dv; mchunkptr top; size_t trim_check; size_t release_checks; size_t magic; mchunkptr smallbins[(NSMALLBINS+1)*2]; tbinptr treebins[NTREEBINS]; size_t footprint; size_t max_footprint; size_t footprint_limit; /* zero means no limit */ flag_t mflags;#if USE_LOCKS MLOCK_T mutex; /* locate lock among fields that rarely change */#endif /* USE_LOCKS */ msegment seg; void* extp; /* Unused but available for extensions */ size_t exts;};
arena header
一组heaps公用一个arena header。
struct malloc_chunk { size_t prev_foot; /* Size of previous chunk (if free). */ size_t head; /* Size and inuse bits. */ struct malloc_chunk* fd; /* double links -- used only if free. */ struct malloc_chunk* bk;};
细化heap,每个heap中又细分为多个chunk
,每个chunk都有自己的chunk header
。
main thread的arena是没有多heaps
的,因此没有heap_info。不像有heaps的子线程arena,子线程的某个thread的用完其初始heap时,如果还要malloc,那么就会从arena中在获得一个heap。而main thread是没有heaps的,当main的malloc超过了其arena界限时,需要从新设置brk()
。
左边是main thread arena
它是没有heaps的只有chunks,如果分配越界需要重新设置brk来得到更多的arena。右边是子线程的arena
,它包含多个heaps,每个都有heap_info,这里是其一个heap,heap_info中可以找到其chunks。最开始子线程thread1会分配到一个heap,当其分配越界了就会从子线程的arena
中再获得一个heap。下图是子系统多heaps
的情况
chunk
从上面可以看到有allocated_chunk、malloc_chunk、free_chunk和top_chunk。
对于allocated_chunk,含preb_size、size、mem和next_chunk。
其中n、m、p分表表示:
bin
bin是freelist的对chunk size进行管理的一个数据结构,根据不同chunk size来划分不同的bin。
=512的chunk,包含这些chunk的bin叫largebin;largebin数组有63个largebin成员,每一个largebin元素含有一个双向链表;这63个largebin的划分是:32个largebin的chunksize是按64字节叠加的,16个是按512叠加,8个4096字节,4个32768字节,2个262144字节,1个largebin元素是remaining size。相邻的free chunk会合并。
特殊的chunk
https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/comment-page-1/
- glibc下malloc的理解
- 理解 glibc malloc
- Glibc 的malloc源代码分析
- Glibc 的malloc源代码分析
- glibc对malloc的实现
- Glibc 的 malloc 源代码分析
- 浅析基于glibc的malloc
- Glibc 中malloc的实现
- glibc malloc
- glibc malloc
- glibc malloc
- glibc的malloc--更多的改进
- glibc中malloc的详细解释
- 关于glibc的malloc内存对齐
- 关于glibc的malloc内存对齐
- glibc中malloc的详细解释
- glibc中malloc的详细解释
- Understanding glibc malloc
- 分页显示的思考与实现
- 递归罗列磁盘内容
- 教你透彻了解红黑树
- ios开发者账号申请流程
- NSDateFormatter转换时间字符串时的时区问题
- glibc下malloc的理解
- Android,iOS打开手机QQ与指定用户聊天界面
- NUI四种提交数据方式
- javascript的历史
- 【排序】快速排序法
- python脚本中的函数开发时怎么调试(__name__=="__main__")
- sql中group by和order by
- IOS开发之使用Speex格式实现简单的语音聊天功能(一)
- 出现这个错误CUICatalog: Invalid asset name supplied: , or invalid scale factor: 2.000000