linux提供了brk,sbrk系统调用来申请释放内存。
linux系统通过一个指针来管理内存,如图所示堆区向上生长,使用一个指针指向堆顶。每次申请内存,使用系统调用把brk指针向上移动,释放内存就把brk指针向下移动。但是如果不想释放data2直接释放data1,这是做不到的。不需要的数据data1,必须等上面的数据都释放后才能释放。
不需要的内存无法归还给操作系统,这就是内存碎片。
一、libc库(stdlib.h)的malloc
malloc使用链表来管理内存。
1、使用brk申请一大块内存。
2、把brk申请到的资源分块,每一块内存都对应链表的一个节点来保存这一块内存的使用情况每个节点包含,地址,是否被使用,大小等属性。
3、每次调用malloc申请内存时,malloc内部会遍历这个链表,如果找到未被使用而且大小也满足,就把此地址返回。如果没有找到就要调用brk系统调用在申请一些内存,链表追加一个节点。
4、如果释放某个内存,就把链表对应的节点的状态标记为未使用,这时候可以进行内存的复用。
malloc函数会直接从linux内核申请一大块内存,供程序员使用,malloc内部进行内存的维护与释放。减少内存碎片的同时,也减少了brk系统调用的次数,提高了效率。
但是为了解决线程安全问题,多线程同时使用malloc和free,malloc使用锁来进行线程互斥,不支持多线程同时申请内存。
2、tcmalloc头文件的malloc
基本原理与libc的malloc一样。不过在多线程同时申请释放内存时,malloc内部不需要进行线程互斥,可以支持多线程并发申请释放内存。
但是内存属于共享资源啊,怎么进行线程互斥呢?
malloc为每个线程都分配一个内存块进行管理。