linux下的malloc底层剖析总结

今天在看了网上一些大神的malloc底层剖析后,自己想对其做一个总结和梳理。


首先我们都知道malloc()申请内存是在堆上进行的,并且需要我们主动进行free()释放,如果不释放的话,就会产生内存泄漏的问题。

而在栈区上是由编译器自动释放的,存放的是函数的参数值,局部变量等,内存分配是连续的,类似于数据结构中的栈。我们生命变量时候,编译器会自动接着栈区的结尾来分配内存。

在32位linux系统下,我们的每个进程系统都会分配4G的虚拟内存空间,其中0~3G是用户空间占有的,3~4G为操作系统占用的空间。在我们这3G的内存空间中,有各种区来存放不同的数据,比如程序源代码编译后的机器指令经常被放在代码段中,常见名有".code"、".text";具体如下图:

全局变量和局部静态变量数据经常放在数据段(".data");

已初始化的全局变量和局部静态变量都保存在.data段;

未初始化的全局变量和局部静态变量一般都放在.bss段,.bss段只为未初始化的全局变量和局部静态变量预留位置而已,并没有内容,在文件中也不占空间。


heap就在bss段下方,它的结构由开始标志、映射区和未映射区等组成,而我们知道,虚拟空间的使用必须要通过地址空间映射的方式,具体映射到物理内存中。

因此在heap中的映射区与未映射区之间有一个标志,就是program_break,相当于一个分界。这也是我们后面要说的中断点。


获取的的break地址后,break作为内存初始地址,malloc也就可以开始实施内存分配了:

malloc()的实质是一个可以将可用内存块连接为一个较长列表也就是空闲链表。调用malloc()后,它会沿着链表寻找一块合适的内存块。之后将该内存块一分为二,其中一部分作为用户申请的内存,另一块则为剩下的内存。接着就把申请的内存块传给用户使用,剩下的则接到之前的链表上。当调用free()函数时,就会释放掉之前分配给用户的内存块,然后接到空闲链表上,最后空闲链表会被分成很多小片段。如果这个时候用户申请了很大的内存,但是这时没有满足的内存块的话,malloc()就会产生一个延时,将很多的小片段进行整理合并,再交给用户使用。


1.malloc的初始化

malloc_init初始化内存分配程序

malloc_init    分配程序的全局变量;

int  has_initialized=0;  初始化标记

void  *managed_memory_start;  管理内存起始地址

void *last_valid_address;     操作系统的最后一个有效地址

heap中的被映射内存边界(操作系统最后一个有效地址)常被称为系统中断或当前中断点。为了找出这个中断点,要是用sbrk()函数,它可以根据参数移动当前系统中断点,然后返回新的系统中断点。

Linux通过brk和sbrk系统调用break指针。

int brk(void *addr);  
void *sbrk(intptr_t increment); 
brk将break指针直接设置为某个地址,而sbrk将break从当前位置移动increment所指定的增量。brk在执行成功时返回0,否则返回-1并设置errno为ENOMEM;sbrk成功时返回break移动之前所指向的地址,否则返回(void *)-1。


2.内存块的获取

申请的内存是由多个内存块构成的链表。

a.内存块的大致结构:每个块由meta区和数据区组成,meta区记录数据块的元信息(数据区大小、空闲标志位、指针等等),数据区是真实分配的内存区域,并且数据区的第一个字节地址即为malloc返回的地址。现在,为了完全地管理内存,我们需要能够追踪要分配和回收哪些内存。在对内存块进行了 free 调用之后,我们需要做的是诸如将它们标记为未被使用的等事情,并且,在调用 malloc 时,我们要能够定位未被使用的内存块。


b.找到合适的内存块

一般查找block的方法有两种:

First  fit:从头开始,使用第一个数据区大小大于要求size块所谓此次分配的块。运行效率较高。

Best  fit:从头开始,遍历所有的块,使用数据区大小大于size且差值最小的块作为分配块。这种内存使用率较高。


find_bloc从first_block开始,找第一个符合的block并返回bloc起始地址,如果找不到,就返回NULL。在遍历时,会更新一个last指针,指针始终指向遍历的block。如果现有的block都不能满足size的需求,则需要在链表后面开辟一个新的block。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值