Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

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

$
0
0

其实说的就是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指针永远指向尾。

谢谢观赏。


作者:ma52103231 发表于2013-1-25 17:26:37 原文链接
阅读:7 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>