|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
; m) {! N9 U' v# @+ ]4 e因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.' I) h6 y8 ]- k; J5 k& e
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:, f. G9 b6 C1 N7 k2 T! G
% X7 l2 j/ }7 U) J7 t1 g2 ~# d. K$ C4 n; W- m9 p6 Q
仅三个函数:1 H" R" @9 N1 J# t
0 w8 U; F- |6 s3 f
<<SmallMem.h>>* q* `& O4 Q1 `( ?. `
- ]/ b2 G& C, |/ X
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
. H' l3 X4 {5 c9 D( u# g
4 g2 C, _1 j0 A2 @. ]9 svoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
' M' l, b# i8 _: ^, V8 k1 _& R 分配成功则返回地址,否则返回NULL. % ?7 l. l, h( C7 R- i( d3 _
. R- f' G; F) c$ s$ ?: K
void small_free(void*mem); 释放内存块.; C( V2 i3 ?0 E$ Q
S" I3 {6 |5 v
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \# m* C2 B6 a3 W' c
<<SmallMmem.c >>' a; ^3 k$ y% |, S% h2 B
3 d' e/ C( B% r1 D" `* j- {
/***************************************************************************************************% y; C$ z' d1 j9 k, U; y7 _
Small Memory Managment ..../ _4 {# n, H+ ?
Copyright 2008 by David Xie - l8 N+ h: N8 g( V& T
, a9 i8 l. L' A! B
Last Change: 2008-10-10
! A& V- z/ a2 r0 M3 i8 {1 j) l8 U; o/ n) N/ U) l4 v% q" w0 G
ListHead Byte: Bit7 = 1 Free Block3 r& g/ c1 i6 c8 h1 {
Bit7 = 0 Used Block0 X% y/ _% C& p2 t9 \& I$ Y& x- J
2 G) {- Q3 n& U. U4 f6 n
Bit[6..0] = 1 - 127 number of bytes of memory block
9 z* ]2 o7 b* r6 T( v* E/ g" W Bit[6..0] = 0 end of memory block
4 K1 R5 O# a' X/ W1 O* u******************************************************************************************************/
( X) I# o7 F! A! M& T0 n- W0 i5 O' O' \: P( B
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
: m+ w* h6 V2 E$ `7 R5 o#define SMALL_MEM __xdata // XRAM: p* o3 q% S0 A) y5 ?7 X
6 b$ _. h0 z) F! L( T& f+ ~/ ~5 R( Q//#define SMALL_MEM_SIZE 2562 J( _: o" m" V* m8 \; U- |3 d
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用./ H7 V: V! r9 ]4 t9 J
) Z8 P" }9 e4 t( \' @SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
% V/ F# u. l2 x" [% D5 }% |4 l& P$ c- b% o* i" W1 J
void small_init()
* c V' }& W8 O0 A0 d# `, Z, M{
& {, p+ o4 S: l/ n1 k& f unsigned int i, n, len;( ] |! a5 T" S% X9 [
i = 0;
7 H, j7 }7 X: S$ A" L3 h9 h5 y n = SMALL_MEM_SIZE;4 x9 F+ N- \. o9 F
8 Q1 H; @* H. |: T1 z6 y
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */0 U, @' q' _7 [
SmallMemory[0] = 0x01;
! J) z$ ^8 G' N1 d K7 ? i += 2;8 b3 ], ~) F( M2 s9 w
n -= 2;
2 l; |; D8 Q" [+ _, J }
+ ~4 h. Y2 V9 q7 @6 Y* `7 Z" n( x {5 W4 B- [+ {
/ v) w$ x# P& F* a. c* j! T while(n>1){ /* Init Empty Small List */4 i: \9 d) _1 n9 B4 Y) n
len = (128 < n)? 127 : n-2;# ^& c2 u1 B: `, @" u4 R+ b+ t
SmallMemory[ i ] = 0x80 | len;
% E/ V5 a( g8 ` len++;: v7 z: p( b9 \2 b
i += len;
/ F9 H5 n) v) A! M- q4 L$ B4 p n -= len;
2 T& g7 C( \0 h7 e+ r }6 H: ^# ^1 ^" I( f4 v3 x! M
SmallMemory[ i ] = 0x80; /* End Of Small List */4 I+ p! @* d7 _" z7 c K9 O( f
}! y1 E/ j1 m/ \5 _2 i& M5 E( p2 O
: p" h8 q, o. T+ l% G! |5 Y
void * small_alloc(unsigned char size)7 K! I0 {/ s G* D/ s+ k
{* M7 w3 C2 t4 O7 h6 b* I1 U; R
register SMALL_MEM unsigned char *p1, *p2;# ^/ p6 g; X4 j6 z
register unsigned char len;
4 L8 S) X8 w/ B: r+ Q( ~* O' r6 B9 Q( S D9 i
if( size > 127 || size == 0) return NULL;/ H* l6 \3 \- H3 |7 a6 Z7 l) o
$ B- K( a. d$ _$ X7 N p1 = SmallMemory;: ?0 e# z) I% n0 J' L0 k% f
while( *p1 != 0x80 ){+ A" z: o& a) o# {8 k2 A
len = *p1 & 0x7f;/ O8 a" ^; r5 D8 `2 ~7 W
if( *p1 & 0x80 ){ /* 找到空的内存块 */
) L8 @7 `/ l9 v7 S, K while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */( g9 R. w4 ?5 O. I' @
p2 = p1+len+1; % F/ E; i* P- I
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
) i# a. B1 G% A4 n4 C7 ^! B len += (*p2 & 0x7f) + 1;# J7 D( N7 `6 k" j; z1 D6 q
}else{4 r4 _/ C4 _& w: A. X, A$ W
break;+ l6 @3 a4 w8 L' Q( M% D
}, u5 w# \- U3 B4 Y
} C0 {: E: [) {3 ^0 F W4 e' \( j
if( len >= size ){ /* 找到一个足够的内存块 */5 {# `$ J, g- s; H( y3 v
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */% T* j$ n0 `2 K+ M. d: L" a$ O
*p1 = size;1 G' M0 B, }, X% p' E X$ Y5 V
p2 = p1+size+1;
) t/ q+ f% z$ {$ A) X+ `! R *p2 = (len-size-1) | 0x80;
' _6 v* O: ] ^1 o& u9 } return p1+1;
$ O+ A7 P0 j. t/ S4 ] }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
5 Q' m' s/ T: j4 q& G1 e5 U, X *p1 = len;
L+ S8 Z6 k4 { return p1+1;* b4 ]1 x) ^; y" e6 L! a0 ~7 z* ]
}
* c4 ]9 W" p. _( i' C& t }" Y! x8 F4 a1 k& K
}6 F3 L% H5 C7 F5 g8 q% g
p1 += len+1; /* 找下一内存块 */3 H& C8 A5 d" _
}
, e4 a @( ]+ `* F return NULL; /* 没有可用的, 返回 NULL */8 x& Y. E! ?' h& t8 q& v' s
}9 i. L) g6 r) w& {8 Q" b
Y1 o# W; \# i, Q6 U: Evoid small_free(void *mem)
+ n! _2 Z! e# `; x) v{% J+ w' @ s7 d2 W
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */1 J3 E7 t' z a: A% n2 w
}
$ S" q; Y4 F* b% F+ Q' b( `
7 _( G3 p% K7 C: r# y- \ |
|