|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).+ l1 \0 ?" R; n7 l8 S0 u7 `
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.+ P( ~! z0 w- E. O W- }' A
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
. v, A) Q- s4 N) ^& b6 W4 Q, f2 W k/ l7 v' Q" g2 ]* r- S
* |) n2 ^+ }/ ^
仅三个函数:: S8 d' K1 ?, W' I9 F) v
" p, a# ~: z. ?. _1 c T
<<SmallMem.h>># w& ]' C% I+ g+ v1 b/ o
& i8 ]: s' [6 l3 z6 Z( jvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
) Y5 u0 z0 f% Z" `9 d# p, i1 S, G
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求., |0 P) x% a* V( ~& ~- Q: M
分配成功则返回地址,否则返回NULL.
. u) X% h3 y0 ^( K9 H& A5 T! ^$ H) X. E( J7 g y8 M( a& H. G5 |
void small_free(void*mem); 释放内存块.
! \& c- l* o4 n9 H" |5 ~, Q2 h- Y" g. v' @3 v! x# ]6 b, [
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4 P; E# n+ t, [: f ]0 {( I<<SmallMmem.c >>6 @6 V( k" V' `4 r& Y1 U+ C
3 S- l5 s% k; w: r/***************************************************************************************************8 Z7 V5 Q6 p1 p" y
Small Memory Managment ....2 u/ [8 H( ~) ^
Copyright 2008 by David Xie . s- \. a. T/ X8 r9 \3 j g
9 n0 }" {! n; n# s9 a Last Change: 2008-10-10
5 k, b8 b6 u' i5 P' L9 D7 ]" i
& I' |. I& K$ U7 I ListHead Byte: Bit7 = 1 Free Block
, e$ y' M4 I; C9 ?. v. }6 ~ Bit7 = 0 Used Block& e3 w; |- [% h6 D
# b. u) d- F6 p5 z& \
Bit[6..0] = 1 - 127 number of bytes of memory block% Y5 g; ]5 e6 H
Bit[6..0] = 0 end of memory block
- k, o; d# V O5 q+ v6 Y******************************************************************************************************/7 s% Z/ Y8 T2 D u( U7 x
% ~( Y9 m2 b3 A }. c i1 Y2 g
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
2 [6 o0 z9 e ^% w, G! }! z1 B0 k#define SMALL_MEM __xdata // XRAM
! Z1 p3 L5 o" X9 G& ~
! |+ X3 g# i, l* M//#define SMALL_MEM_SIZE 256* n8 M$ K% o9 H S9 J# }8 k1 F9 C% O
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
; A! L. Z* u: i' _& d3 a; K) l( t P& {9 `
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
1 K3 I" B, k3 o6 O! v: v4 h' W! {4 s$ i6 [5 {2 h- a& X, ?
void small_init()( K0 { U1 a3 R: q$ Q8 N( n4 E
{
# G+ B; I) T* s9 d9 t unsigned int i, n, len;+ x9 q$ P, }1 Z
i = 0;- Z5 [" S* E9 F
n = SMALL_MEM_SIZE;
9 z. p$ X ^! o, v3 M
u2 P1 i1 h: {: r' C* ^ if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
7 m1 x. a% e4 U4 u6 X. K3 V5 V/ i SmallMemory[0] = 0x01;
# r( S$ [* @" D- [9 I i += 2;, H6 w* X- i. l9 w. d- h
n -= 2;3 O' l: g% M- T& l( e
}7 g9 O* _: }; B. h: j9 k; ~% _0 C. P; o
+ O/ ~3 m( z) \0 H0 b8 c( q/ L. u! H
2 f& U6 }7 \' L# Y) p
while(n>1){ /* Init Empty Small List */; G) V: Y3 j. _! Y
len = (128 < n)? 127 : n-2;
. c3 O, f* s. c4 ?; s4 \; T+ A& M SmallMemory[ i ] = 0x80 | len;
. G9 v r' Q+ ~7 w, P len++;
" m5 ?- W- k/ q6 H) C) U j, x i += len;
% q" @% f& e) ^. r# }0 _% F n -= len;
6 N6 t G& |8 a& j0 G3 T2 j7 W }6 |6 Z. |0 n. S" j8 v
SmallMemory[ i ] = 0x80; /* End Of Small List */
) Z) M, C) I/ Z% s7 u8 `7 G} J% J+ I* }# ]' f$ A
# C- f& u- F) K4 a* o8 k4 m. s
void * small_alloc(unsigned char size)+ e/ _9 T, R7 L6 _' ]% [1 _4 F
{' A) k+ }) T8 w+ f1 G4 J
register SMALL_MEM unsigned char *p1, *p2;! u* F4 c" c! v$ _6 c
register unsigned char len;
0 a& g; U% h' p* O- Q; I0 e
v* m* S: t5 z3 C if( size > 127 || size == 0) return NULL;
2 U J8 ]4 T+ i7 B! b
) S! y1 i9 N# M/ u( R' o p1 = SmallMemory;
, C4 _$ c+ F, ` while( *p1 != 0x80 ){
) }4 F0 W6 j% l, W: I len = *p1 & 0x7f;
5 ?5 Q( q) r! }9 m, ?1 W if( *p1 & 0x80 ){ /* 找到空的内存块 */( W# e7 G, |; z7 u5 y* S
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
' b8 _; |# E1 }9 q1 \! j d p2 = p1+len+1;
u& p. _! T4 X0 Y) ~7 k if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
4 \$ P+ ~5 t8 S/ G len += (*p2 & 0x7f) + 1;
o; I1 c0 t( J }else{0 {5 z8 I, n9 `6 U, @
break;
# ]7 B3 g1 ` r: x }/ h7 ?$ H0 `6 K+ H
}; c2 y1 Z. x, [6 t; _0 g% O
if( len >= size ){ /* 找到一个足够的内存块 */3 P3 m: R& ]1 W. `( X
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */5 L) z$ B% S) T! P1 R0 Q9 k, k4 |
*p1 = size;
) L# m$ w- O$ x: X) D& z5 G p2 = p1+size+1;+ u U9 N, r8 a# ?
*p2 = (len-size-1) | 0x80;* y& H& R e$ V# y' l
return p1+1;7 r( d5 c1 Q- i2 ~+ @0 U" |/ }0 i' I# h
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
6 G; D* _4 J/ ?( u( l" P *p1 = len;
; |2 v& {5 |2 a0 q return p1+1;
8 p: {+ L f; a8 E$ N( e+ |$ A' r }7 p+ c* R2 c, F3 |* ^
}8 L P6 [! B3 C* N1 b+ W! j
}# f* j {+ {2 g
p1 += len+1; /* 找下一内存块 */
- [% H0 `+ p, y, q3 ]1 r! a }, k! f% ]# ]8 d3 `1 h: u& f( H
return NULL; /* 没有可用的, 返回 NULL */( a& ~+ Y, {' _
}
5 C7 U7 K" B& I% j( P: z* s
) w: |6 r! X5 W. j) W) ?3 F) J6 Tvoid small_free(void *mem)& H. N- i- w6 J2 Q% R B
{
8 f. ?. k& B7 P4 Z+ Z$ X3 ? *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
/ y! n1 Z9 a& s: ~- |}0 \8 i. Y" u3 }3 I+ P
: k1 I2 R2 w* U' f# g1 p
|
|