|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
& Y. N5 c- c" k A% L) O因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
" Y* i5 ~7 u$ K, H3 S正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:' t, b! I2 i* }
) [- Q3 u4 m) M( X
# ?! E/ h# k) j7 V
仅三个函数:, o5 l( p' f1 i' x/ _
" u3 C" _6 o d1 J) p. ^
<<SmallMem.h>>0 A& a: M2 x/ k+ }; p, X
/ {+ r5 S [* qvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
! O6 Z/ b. Q' @! l! N' T
$ U8 ^5 U9 Y6 t( i6 Rvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.+ a- l0 P m& I) J) w
分配成功则返回地址,否则返回NULL.
4 c- G4 ]: H5 V9 f( Q1 Y3 b4 j7 O+ f
void small_free(void*mem); 释放内存块.$ f1 n( j$ t5 s: y9 E2 a( Z6 O6 [+ b
5 g5 w2 F) D7 q7 B-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
( M, d3 ?' ^% k% ]* y$ ?9 h<<SmallMmem.c >>/ B1 |7 j/ x `7 u. K ^
# Q6 m# d4 b9 |* O+ x0 g
/***************************************************************************************************
. W; A& Z a* N% f$ y! A: Q Small Memory Managment ....* x: B2 A: w8 f/ q
Copyright 2008 by David Xie
9 j5 m0 F& ~! y6 v1 d
# v& R6 C7 X1 W- N Last Change: 2008-10-10
/ ? p$ h+ L1 ~+ e. q0 h& v# v6 u* h1 x0 D$ h6 L/ t" N- S
ListHead Byte: Bit7 = 1 Free Block
+ @1 m- L0 u4 `. c+ z5 z Bit7 = 0 Used Block
& N, I" C x5 W7 V# V& ]
7 G, [7 l: ~# a9 o Bit[6..0] = 1 - 127 number of bytes of memory block. U3 J! T- p$ _0 S# Y9 t y( L0 |8 Y
Bit[6..0] = 0 end of memory block* a: R: x" o! ]% `" s
******************************************************************************************************/# T* [8 E) W( ~9 ^
: D% c: A5 u9 b2 ], r" e#define SMALL_MEM_SIZE 1024 // 依你的系统来定./ f* a0 o5 t& t ]# f
#define SMALL_MEM __xdata // XRAM- K+ r+ i. l6 W7 ?, E
) G. }! ^, Y5 Z3 {' h: ^
//#define SMALL_MEM_SIZE 256
, ^' z8 c% W5 V; A: s n: k//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
. b" o7 C1 W* t6 L4 u
: @9 y% S$ L6 z+ E3 }6 eSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE]; }1 ]. e* h3 ]: y- p
2 f/ E. V, H( I* _7 b( R/ Y6 d7 Pvoid small_init()
& {6 d( L5 H9 B* d" p{
8 r$ z( I$ Z. d$ K5 H unsigned int i, n, len;. J8 |! n! D3 Q' H* m5 O m# i, R0 n
i = 0;0 ^3 k8 R; T* @& r& ~
n = SMALL_MEM_SIZE;5 b9 O/ a2 U$ p
, p8 c# z- N' U4 ?* Z if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */7 W% a' [, S. o- \3 `
SmallMemory[0] = 0x01;: [7 j% D* Y# H5 r4 o1 e
i += 2;
2 Q' z# k2 W' M5 b4 L- Q( W n -= 2;% \4 S1 z8 [0 S8 P4 O
}
4 |' s$ O/ F5 P$ B3 M& f& t/ _' e$ A
7 o/ W1 ?, S4 l$ j while(n>1){ /* Init Empty Small List */
/ y4 J% P" \+ l; W% M) U len = (128 < n)? 127 : n-2;
& H( y/ u' i/ J% q' O" Z SmallMemory[ i ] = 0x80 | len;# P0 {& u* V( f" h# z* I: i- N: P
len++; E& i) y, a/ t' r+ @
i += len;7 ^3 d+ j1 d3 x" Y3 ]7 w' F
n -= len;! u! s& V, a/ q: f8 m m% U. t
}
. L `, C4 @# J2 F1 W4 o7 ` SmallMemory[ i ] = 0x80; /* End Of Small List */# M7 ?3 j2 U5 w/ p
}7 V, {" B1 z$ l3 s" @/ E
6 }+ D# q5 R# I8 Q# x: T: c. y
void * small_alloc(unsigned char size); Q, v' y, d* I1 C: n
{% N7 L2 C) m4 ~ y* g& Z1 z
register SMALL_MEM unsigned char *p1, *p2;
+ e! W2 D! x2 f- d register unsigned char len;3 T4 H& P# P1 M5 Q) M3 I) l
# t0 ~2 ~ ^7 J if( size > 127 || size == 0) return NULL;
. s: Q: U1 V/ o* w
4 h1 F% m) `7 s3 w! G0 M2 { p1 = SmallMemory;
' {/ W& K4 x1 L5 f while( *p1 != 0x80 ){
( y/ [/ l- I& V" S len = *p1 & 0x7f;
% I. ]$ E0 B' b if( *p1 & 0x80 ){ /* 找到空的内存块 */
7 Q1 a* \* E s/ O: I/ f d3 G% i4 ? while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
7 s4 T2 a: D. b p2 = p1+len+1; 4 U/ e, l0 _. P, `
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */ W T& S& r3 x$ O9 e! c: z2 V$ f5 q
len += (*p2 & 0x7f) + 1;4 t0 m- ~+ |! M* b/ d- ~
}else{) w" E. a2 ]; ~' ~1 G
break;
9 m2 `" J3 T0 e' M }
* n1 G2 h( v1 r8 }' e( q2 e: ]7 S }
1 W6 b$ H0 \1 w if( len >= size ){ /* 找到一个足够的内存块 */
1 [. v. y" ?& i( a" k8 a+ J! M if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */# ]& n* L O: s* Q# X1 H
*p1 = size;
$ C# t. k8 K& P8 n& B9 u p2 = p1+size+1;' x! E2 \" k& P* F- v4 a; l; v
*p2 = (len-size-1) | 0x80;
$ [: u" u8 F: `: P7 u1 J return p1+1;
; y9 C. x: i4 E. T }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
/ ]! m: j; ~% w *p1 = len;
" E: k9 a( [" ]/ c4 l" o' d, n return p1+1;' l4 P4 q/ C" }! N) r
}
* `& i. _* H1 r; i# [$ \9 @$ E }
; b/ R( M5 Z5 E! B; | }
. _: e$ b/ r- x% a# f& o p1 += len+1; /* 找下一内存块 */2 G8 \+ x8 F$ ~; X4 S
}5 L1 ]/ P2 u2 B- ^/ }
return NULL; /* 没有可用的, 返回 NULL */
0 c+ g0 h$ O* J, S* L m- P7 v, O, M}1 r' v8 s( n, b7 Q, v
( t @/ x8 x# }! Evoid small_free(void *mem)% R8 P1 i7 I4 j9 G! q {
{1 P5 `* U* b- y1 i
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
3 N" ` s( r4 S* F; \% `}. ]' w2 ]# q2 Y; e" ?; h! @
9 e5 r: P, N" B( x |
|