|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
* S/ m2 y! B0 k4 h# O6 ~+ j% D因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.& A0 S+ b: ?1 {/ v
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:! ^0 }; F, s. `; b2 N
2 \; G! D0 B/ b, g' U
" @3 g/ d# B, }
仅三个函数:
, P' w9 C: e$ f0 h; I: P/ m* H* H% `
<<SmallMem.h>>
1 m$ s$ H# H" ~8 [# h' B
' O; ^' V P" `% S; r! [void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
3 g( i6 J; Y4 c' y& t9 }* U3 ?2 `6 ~% k
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.7 {2 b! p9 e& s# q) n- E o
分配成功则返回地址,否则返回NULL.
& Z# w. C; M5 m- G
1 R/ N5 C6 i& M5 C Kvoid small_free(void*mem); 释放内存块.& i1 q+ x- H6 |$ q7 Q- y
5 {$ }; I( w( K' f2 ?-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
) n2 a; E, r7 H<<SmallMmem.c >>$ j: `% j8 D+ }: L8 \+ O. O
: |; }5 j" s: ]) z7 b$ s$ y( {! D% E7 l/***************************************************************************************************
& h! g8 m/ j. i$ `- G Small Memory Managment ....8 c/ L( g" S" |# @+ m
Copyright 2008 by David Xie
- S' t3 {6 b8 o) n/ B* l8 b5 @
+ c. A* s0 N( I7 y* p$ { Last Change: 2008-10-10; O: ~* L5 x/ k# h( @" Q) x
o0 e. B! ?1 {( m; Y
ListHead Byte: Bit7 = 1 Free Block
% g* C H M6 U3 }# V: Q, l2 D Bit7 = 0 Used Block$ Z" G. m8 V5 {0 K* }
, b8 ~( T6 T4 e. l0 |4 L# c
Bit[6..0] = 1 - 127 number of bytes of memory block
, ~3 j" a, g W' P5 L0 |" o E Bit[6..0] = 0 end of memory block
* W9 m6 S( p. F" |" ]******************************************************************************************************/4 s/ A: k( z1 X b
: [- _/ O8 N" f( [#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
$ h9 ?% c' ^$ Q! N#define SMALL_MEM __xdata // XRAM
q. U- p; x7 P' B* [0 a- i l' s3 s
//#define SMALL_MEM_SIZE 256# k: W- Z6 y( r9 b# w- d
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.% n# g! C; Y+ K. e
& i1 Z+ E8 I% Q( H4 f: h3 ~. F: V; `% uSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
3 \* G5 f5 {; D# Q+ X. G# a
- C, e/ i$ k! S* |1 S- X; jvoid small_init()* t6 h- s: q4 q7 k8 B/ g4 E
{
# l. h# U# w% Z( ^ e2 u: Y, A unsigned int i, n, len;( q8 w( c2 q! g. ^
i = 0;. o) M# n1 x* G) g6 {
n = SMALL_MEM_SIZE;
/ T3 l" V' c1 P y+ [0 Q2 D6 b6 S: Z% K# @. D, ^6 Z
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */, B5 o. U( s) U, s3 f+ z
SmallMemory[0] = 0x01;
4 w" w; s5 t2 a1 h0 ^) y i += 2;
9 k, e; D! c# P& W6 i! g ] n -= 2;8 K C! l+ J% n" |& j6 t6 K
}6 r# c* z P9 I3 r! }' V, F5 }
3 U' t" U! \% B5 Y$ } d0 \
' B) b+ @6 p2 t& \7 n
while(n>1){ /* Init Empty Small List */
7 U* W1 z+ [ v" X$ F' b len = (128 < n)? 127 : n-2;
$ Y2 x8 S6 D2 V SmallMemory[ i ] = 0x80 | len;
! u q& R5 i. f% f5 J len++;+ B3 D5 h7 P+ a& x0 r- Y
i += len;
( p7 u( q9 |+ `0 s1 x& b2 J3 Y n -= len;; U3 s9 k6 w7 ~2 k+ P
}+ {! ~: L# T2 J
SmallMemory[ i ] = 0x80; /* End Of Small List */0 r, | s7 c+ a
}( n; J) m u! [0 O1 Y
' s: l4 m3 u7 \$ p+ w$ u9 K) |
void * small_alloc(unsigned char size)
8 z, @8 z( x/ h0 R6 w/ J+ Y{' g- Z7 ?2 ~- h H% i6 }0 O
register SMALL_MEM unsigned char *p1, *p2;
0 \& H% d n2 W/ R0 x- U register unsigned char len;$ d9 a* r# F* J3 Y# _
( f$ i- s# g4 V/ t; c if( size > 127 || size == 0) return NULL;' M1 t3 I$ R3 v$ J/ N
5 Z' t) p8 E- E5 G- V% M& w p1 = SmallMemory;) j3 i6 {7 C) K7 O
while( *p1 != 0x80 ){' J" v9 N( ?! O! D+ n9 z
len = *p1 & 0x7f;, L" s B! o$ ]
if( *p1 & 0x80 ){ /* 找到空的内存块 */) \) @+ T- x# p1 d
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */! m4 x. `; D t' |0 u3 f. N
p2 = p1+len+1; % Y/ G' l% C" B" h( W$ X8 _
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
' Z# U3 `7 H* r/ [" _- e: o len += (*p2 & 0x7f) + 1;% u% k# L6 O1 X* C' e! y
}else{
9 U2 C- j$ G4 E6 } break;5 ]- i2 ]1 l k Y
}0 B8 w, Y% x# X( z; p7 O* V
}( f* G+ N4 X+ ? S( v2 `# K |, Q+ B
if( len >= size ){ /* 找到一个足够的内存块 */7 f- n$ W8 j! X+ v( S
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 *// h- q1 H5 \; j$ R9 b ]
*p1 = size;/ ]+ I q7 h8 ~2 M. E7 X
p2 = p1+size+1;
( [. p; I+ y" k' i *p2 = (len-size-1) | 0x80;/ g/ f' F( j( a5 ~, T* T
return p1+1;7 x& B2 B# p2 A' g
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 *// K/ D/ v+ l' v+ a1 y; z- W
*p1 = len;- v1 }3 [$ y5 g+ n, s( w- D
return p1+1;
6 \ H4 K) J4 ]9 `+ {1 d }
}8 A& d7 ~% ]" G }
; Y# Y% r: ?. O }
4 t: w7 I' P9 J p1 += len+1; /* 找下一内存块 */) q1 M2 s- W) k
}1 _' F D' Z9 F- _: r
return NULL; /* 没有可用的, 返回 NULL */
2 _) o# `/ O0 r! F: X9 \$ Z}
% t+ R& B- ~/ |" S! Y8 I, i& [+ q" S) O
void small_free(void *mem)$ x9 b8 j5 O. ~: o) H* Q
{: m% `" j0 w# \0 T% ~& d
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
( x: Y$ X$ a# d0 f8 H}% L1 `! @: I/ T2 x4 G1 u, Y
! x3 r( z: S0 M+ S8 e5 m |
|