|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
+ d- w5 v+ R( I3 m3 B3 F$ H1 S因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
& [8 [; ]/ A) k正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
8 D5 T5 x- ?# H6 m& Q
8 C3 n. A+ w3 U" K! }8 y+ c$ G/ \$ s3 l" M, C
仅三个函数:: \/ o0 k( i2 L% t" f$ q
4 `" G6 A. J7 z8 p( Y7 @7 L0 K<<SmallMem.h>>
( P: D- m ^% b2 H, n1 r
/ h4 X+ V) o) l0 n8 x. Ovoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块./ z0 q' h y Y3 Q: F( Z/ w
+ C+ Q* D& l% C" hvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求." [. P- Q7 b: z: B
分配成功则返回地址,否则返回NULL.
& ?0 e$ Q+ D, m/ w4 [1 I* s. K3 x/ D0 a+ v# m5 g! e5 N1 ~
void small_free(void*mem); 释放内存块.
5 {& R2 _2 W# z* q3 r* X! {4 i3 Q
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------/ M, ?8 j% `' \6 ?* E$ C% j
<<SmallMmem.c >>
5 j% N F. }$ ]6 w+ D! k
3 T* M. L5 y2 K' H4 g/***************************************************************************************************
\% E8 @+ M! t, v5 j: t( f Small Memory Managment ....* @! `$ S+ r5 n( P, `) {$ c5 ?
Copyright 2008 by David Xie
, a5 W5 K: e& \5 X' _; _& f) M2 }$ F5 [. s7 E
Last Change: 2008-10-10
) M4 G: U, J% F: Z' z) m8 W1 M8 R! F
ListHead Byte: Bit7 = 1 Free Block) @0 ?& r( r% E- ]4 D* w
Bit7 = 0 Used Block- Z, A# I" o g( M c
2 n) z+ I) ]8 t' S' U% D3 s( R4 @ Bit[6..0] = 1 - 127 number of bytes of memory block
+ P9 g# I4 [6 R! b _' W$ x7 r Bit[6..0] = 0 end of memory block
+ v; G6 G( ]/ @- R* n) Z******************************************************************************************************/
) r; M0 ]4 t9 d* |/ P
# o& F' r' Z8 q' W#define SMALL_MEM_SIZE 1024 // 依你的系统来定.& a I" t) ]. e" c
#define SMALL_MEM __xdata // XRAM
: C9 e2 X; d, ^6 S) Y
# O* [/ h6 C9 S( y//#define SMALL_MEM_SIZE 256* |1 h3 G5 Q! |2 }+ N2 C- e
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.4 B( c% Z3 ~3 f& d- H
: M; S- c5 Z5 u4 i% n; X
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
- r& D0 X( J6 L# j4 O
/ N; S/ H9 U6 w9 i' q @void small_init()
?2 H/ a! s/ `4 J{/ p% p* r& j' D" f2 @
unsigned int i, n, len;# W% L& P- e+ r0 N' N
i = 0;9 }' R7 i! s% _/ `" s9 l g; d) `- s
n = SMALL_MEM_SIZE;
6 r3 @" ~9 N+ \; W- E: p% n$ g; z, f2 Q" e) [# v9 v4 H3 _
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
4 ~) D# l" V1 }% H7 c% _8 t SmallMemory[0] = 0x01;
& W; a$ j6 @2 T" a# H% @' s i += 2;/ b$ G2 i5 L; @
n -= 2;
6 B( L+ O* U* ]! S ]" u }
% k! a5 d' x: w0 [7 \, t1 U+ A4 q/ n. b2 K$ S% s1 P+ G0 [) a
* c3 @( T p4 v& P* z V
while(n>1){ /* Init Empty Small List */" |& `+ L9 r+ o4 C9 Z- ^
len = (128 < n)? 127 : n-2;& t; C$ |% }& R# t; s. x' s/ p
SmallMemory[ i ] = 0x80 | len;
5 L0 n7 \* m' Y/ h: X len++;
% c; o0 L# m( ]" x i += len;: S2 h1 t8 f' }& D4 u7 m/ M
n -= len;
& W/ d- t( n* N: |+ \ }- I4 Q4 l4 i5 x
SmallMemory[ i ] = 0x80; /* End Of Small List */; I( l. u4 G; n1 c' q: P( F$ K0 F1 I
}
, b! [6 N! Z! J; D' T
8 t0 l& X' `% K) H, ]void * small_alloc(unsigned char size)+ i0 v1 s* }8 f( m: ]
{
3 f9 O; H8 l" f2 p4 u register SMALL_MEM unsigned char *p1, *p2;
1 S( Q: {0 j- O5 Z& g register unsigned char len;
A: a; J3 i4 o8 G2 v/ D* U0 o7 e+ [+ q+ e9 V5 ?
if( size > 127 || size == 0) return NULL;
7 f) m- n; w" q `- k% i6 V' c( i9 b8 N, a
p1 = SmallMemory;! x% J3 B4 y' A' K& i* b9 [9 U: P
while( *p1 != 0x80 ){. ~6 b- l% `3 l2 B2 I! w' Z
len = *p1 & 0x7f;; k! Z( {, ^+ I: j
if( *p1 & 0x80 ){ /* 找到空的内存块 */
$ Z2 v& w6 G& k/ T while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */9 Y& V0 T, |1 N0 I h
p2 = p1+len+1; ' e" ^( `9 \% a& w
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
) q' E2 w: K: K+ O4 L" ? len += (*p2 & 0x7f) + 1;
; y6 U% c3 u# g4 E5 j }else{
8 `8 i. X0 _, S( ~" v break;
7 L- ^% u& s# z" X, H }
6 k! k/ w; C. {" t0 E( Z) c }0 |; J& ^7 X+ ^. G6 g
if( len >= size ){ /* 找到一个足够的内存块 */) ]! L( |0 X- n( E4 S6 |! i" l
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */6 l: w. c2 l4 y1 m
*p1 = size;
4 ~6 p) y0 r+ p5 v7 @, L p2 = p1+size+1;
/ \0 {" ?7 [' a *p2 = (len-size-1) | 0x80;
* W0 R# ?0 K6 G! w' v return p1+1;; [- }9 u+ s2 N6 i. T8 c
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
) q' a! f J) Z2 `3 Q( X *p1 = len;
5 f/ X9 A" x9 H) N7 K4 B return p1+1;
, S0 W$ n$ o5 a8 r2 m6 a }. s- n4 X4 W$ @; I
}
6 v$ k4 @" D. m3 n' U }& K1 h& T, }3 e. y1 J
p1 += len+1; /* 找下一内存块 */. j0 ?! \2 n+ C/ a- q k
}
K! Q! l/ ?: X% q+ S' i7 c return NULL; /* 没有可用的, 返回 NULL */
+ [5 a* c7 x7 h Y: R+ y}
2 w' j+ X9 }# e5 a
+ M9 G# l% B' P. s3 A' kvoid small_free(void *mem)
1 Y: _6 x' @1 r' v: ?. P{
4 f1 {2 r' X( w6 @1 x4 Y+ E *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
: R: }( O3 S( @2 U4 \- Q4 }' ^- Y/ @/ G}
" s6 H; v0 j! T3 o* X; h4 O$ j, H9 ?' d/ |& j' \' n6 [
|
|