阅读《C 风格的内存分配程序》有感

来源:互联网 发布:淘宝新势力周多久一次 编辑:程序博客网 时间:2024/05/01 07:17

其实说的就是C语言的malloc和free的实现机制,实现算法。在阅读了内存管理内幕(以下文字基于这个链接)这篇文章的前半部分后,深有感觉,这全是重要的思想啊。

关键词:内存控制块MCB

MCB这东西是一个结构体,具体定义如下

struct mem_control_block {int is_available;//这个字段值为0的时候表示还没有被其他程序使用int size;//这个字段表示这个MCB示例所管理的内存长度};
除此之外,需要三个全局变量来控制分配程序的进行
int has_initialized = 0;  //决定分配程序是否已经初始化void *managed_memory_start;//保存系统返回的系统在用户任何malloc都没调用前的当前系统终端点void *last_valid_address;//同上,不过这个值会在每次malloc()之后得到更新,指向最新的地址

好了,有了这个基本的概念,开始分析吧,会慢慢了解到以上变量的作用。

c的分配heap程序在开始运作之前,需要初始化,就需要调用

void malloc_init(){  last_valid_address = sbrk(0);                  //你看,先返回系统的当前终端点  managed_memory_start = last_valid_address;     //保存一下  has_initialized = 1;                           //表示已经初始化过了}
这个函数就不再被调用了。

开始首次调用malloc()

last_valid_address |managed_memory_start | ----------------------------------------->
首先,可以理解这两个值指向同一个地址

在此之后,把用户请求的内存长度加上管理这快内存的MCB长度

    memory_location = 0;      current_location = managed_memory_start;      while(current_location != last_valid_address)  
执行到此处时,由于是第一次使用malloc,所以发现while条件不成立,离开了

    if(! memory_location)    {      sbrk(numbytes);//把中断点移动numbytes个字节      memory_location = last_valid_address;//把这个变量的值给要返回给用户使用的变量      last_valid_address = last_valid_address + numbytes;//更新这个指针变量,为下一个malloc做准备      current_location_mcb = memory_location;//把MCB放到此处      current_location_mcb->is_available = 0;//设置0,说明这块内存已经被使用了,以后对这块内存的返回都是不允许的      current_location_mcb->size = numbytes;//设置MCB要管理的字节数    }
managed_memory_start                    last_valid_address |                                              |-------------------------------------------------------> |<--1-->|<----------------2--------------------|> | current_location_mcb 1:内存控制块长度 2:用户请求的内存长度
1 + 2 = numbytes

最后来一句

memory_location = memory_location + sizeof(struct mem_control_block);
并返回这个变量,所以,我们用户使用的内存控制块后面的那段内存,MCB对我们是透明的。malloc目的达成.

对于free的话

void free(void *firstbyte) {   struct mem_control_block *mcb;    mcb = firstbyte - sizeof(struct mem_control_block);   //把地址回退到MCB的位置  mcb->is_available = 1;                                //再把MCB的管理标记设为1,说明目前没有程序使用此块内存  return;   }  

那么对于第二次malloc的话,很明显

while(current_location != last_valid_address)
将成立

进入循环体后,先得到current_location这个地址开始出的MCB,通过强制转换

current_location_mcb = (struct mem_control_block *)current_location;
得到。

下面的就是判断可不可用啦,长度够不够我要的啦,其中只要有一个不满足,就要找下一个MCB。

一环套一环的能找下去的根本条件就是本次得到的MCB里面的size字段,不断照着它偏移就可以了。

如果可用且长度够,那么就把current_location + MCB长度偏移后的地址返回给用户使用。

如果执行一次就跳出了呢,那么就照着第一次malloc的方式再分配内存。

如此如此.

总结一下:这个分配算法有点像我目前做的网络通讯协议,数据包括报头和数据段。报头定义了一系列有关数据的属性。看来都有通性。

managed_memory_start一直指向第一个地址(暂且这么说),它是一环套一环查找的基础

last_valid_address只要使用了malloc,就得到更新。

现在想想,怎么这么像队列呢,一个head指针永远指向头,一个tail指针永远指向尾。

谢谢观赏。


原创粉丝点击