Pooled Allocation池式分配实例

最近翻看Kei安装目录,无意中发现C51\LIB下的几个.C文件:

CALLOC.CFREE.CINIT_MEM.CMALLOC.CREALLOC.C

看到 MALLOC.C 和 FREE.C 想到可能和“内存管理”有关。花了半个上午把这个几个文件看完,感觉代码虽然短,确有几个巧妙之处。看的时候也有几处疑问,看完之后豁然开朗。

1) CALLOC.C

我首先点开的是calloc.c(因为calloc()平时没怎么用过,最为好奇),看到了这样的代码:

1: void _MALLOC_MEM_ *calloc (size,len) 4: { 5: void _MALLOC_MEM_ *p; 6: 7: size *= len; 8: 9: if ((p = malloc (size)) == NULL) 10: return (NULL); 11: 12: memset (p, 0, size); 13: return (p); 14: }

这个函数很简单,它并没有直接获取内存,而是调用了malloc;看到这样的代码很容易想到——这是一个用来分配动态数组的函数。size是元素大小,len是数组长度。应该是这样用的:

1: int *pBase; 2: // … 3: pBase = (int*)calloc(sizeof(int), 10); // 10个整数 4: // …

在calloc里看的了 _MALLOC_MEM_ 让人不解,顺着CALLOC.C的#include找上去,看到了:

1: #define _MALLOC_MEM_ xdata

原来是这个… …(如果有同学不知道xdata是什么,可以简单的理解为“堆”。管它呢!)。

2) MALLOC.C

继续点开MALLOC.C(这份代码不短),一看到头部,猜到它可能是个链表:

1: struct __mem__ 2: { 3: struct __mem__ _MALLOC_MEM_ *next; /* single-linked list */len;/* length of following block */ 5: };

很明显,这里的next用作链接;但是,len的作用暂时还不能确定(猜测:标识空闲块的长度,注释说的)。它们是这样:

接下来是类型、常量定义定义:

__mem____memt__; 2: typedef __memt__ _MALLOC_MEM_ *__memp__; 3: 4: #define HLEN (sizeof(__memt__)) 5: 6: extern __memt__ _MALLOC_MEM_ __mem_avail__ []; 7: 8: #define AVAIL (__mem_avail__[0]) 9: 10: #define MIN_BLOCK (HLEN * 4)

看到这些typedef,#define也不能确定各自是做什么用的。但是有个extern声明的数组!应该在别的地方有定义。(关于声明和定义不多说了)

然后就是完整的malloc()了(部分注释已被删除):

size) 2: { 3: __memp__ q;/* ptr to free block */ 4: __memp__ p;/* q->next */k;/* space remaining in the allocated block */ 6: 7: q = &AVAIL; 8: 9: while (1) 10: { 11: if ((p = q->next) == NULL) 12:{ 13:return (NULL);/* FAILURE */ 14:} 15: 16: if (p->len >= size) 17:break; 18: 19: q = p; 20: } 21: 22: k = p->len – size;/* calc. remaining bytes in block */ 23: 24: if (k < MIN_BLOCK)/* rem. bytes too small for new block */ 25: { 26: q->next = p->next; 27: return (&p[1]);/* SUCCESS */ 28: } 29: 30: k -= HLEN; 31: p->len = k; 32: 33: q = (__memp__ ) (((char _MALLOC_MEM_ *) (&p [1])) + k); 34: q->len = size; 35: 36: return (&q[1]);/* SUCCESS */ 37: }

稍加分析可知,while(1)是循环遍历链表的(循环内的p=q->next和q=p这两句)。所以q一开始指向的应该是链表的头结点,AVAIL即__mem_avail__[0]里存放着链表的头结点。由16行 if(p->len > size) break; 可知,len的作用确实是用来标识空闲块的长度;所以整个链表应该是这样的(绿色部分为空闲内存,白色是链表节点):

由此可知,注释里的free block指的是一个“白色+绿色”。

注意,一旦满足条件(找到一个足够大的空闲块),跳出循环时,p指向这个“够用”的块,q指向p后面(与链表方向相反)的一块(如上图p,q);

从一开始就提醒自己,世上没有后悔药吃。

Pooled Allocation池式分配实例

相关文章:

你感兴趣的文章:

标签云: