|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了)." w0 I7 [$ e. E2 ]3 U+ ]+ z Z
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.6 B) Z: U- `6 j
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:# a0 W! z4 @0 m( e1 C3 ?9 h
1 b& B$ L1 p: P; b N
$ |* J/ _# i; i3 \8 K仅三个函数:
8 K0 e- C/ G8 Z" Q( |
% V6 P4 a0 s# A! E+ @) b) t* E<<SmallMem.h>>
! [5 T* s5 [0 h. ~& T5 ^: X) ]6 z) R- I4 A+ C3 D& o3 Y Y
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.8 G2 r/ R( f/ C# m, r4 H* c' V
3 z% m3 z- T6 l
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.9 Q2 z) O% X! v* w) M2 s+ M: m$ p
分配成功则返回地址,否则返回NULL.
5 r2 V2 k8 S& n3 |3 T& G% e! s+ T
void small_free(void*mem); 释放内存块.& W+ H9 ~5 j L, V7 n) T9 q `
0 W/ U# l |7 [1 Z-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------" Q4 k" Y! v/ J; [# ?) T7 g
<<SmallMmem.c >>
$ f/ ?9 ?$ ]% E& t3 i: r5 s: U! B: ^
9 _+ Y5 K/ _5 y9 Z/***************************************************************************************************
1 T+ C4 B& x+ l: x Small Memory Managment ....
- P! a) l% T9 ]' I6 C Copyright 2008 by David Xie 9 g6 m5 s `* M* l8 C4 W
! J0 N$ D; L) R& b/ H$ ?
Last Change: 2008-10-10
4 n/ I+ l* X+ z2 |1 l- n4 q4 w& V) T+ A
ListHead Byte: Bit7 = 1 Free Block
' J, \' H$ Z2 }. k7 y" `/ W Bit7 = 0 Used Block. `; p$ z! R* f, c& _
/ _. S2 @* e n9 y7 w. m9 Q
Bit[6..0] = 1 - 127 number of bytes of memory block
+ B/ V8 V$ S2 Y: D" q6 k! Z1 T9 T$ O Bit[6..0] = 0 end of memory block2 X0 l# V' m0 m0 w
******************************************************************************************************/
' @+ u8 ^. I- C* d. e
: U+ o0 a. s9 R; H2 S#define SMALL_MEM_SIZE 1024 // 依你的系统来定.7 y) l7 a4 w& K3 f0 j
#define SMALL_MEM __xdata // XRAM
' A6 |- E% r1 r% Y; u' }5 g: X
E M3 R$ s" }: `//#define SMALL_MEM_SIZE 256( q) f8 A7 y( K: y% Z- e( G
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
9 s/ ?3 ]" j( ?* p$ Y, c W- v1 c$ {* @ T/ @+ v
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
7 D2 ~+ m8 r& T/ J9 W+ Q& e( f1 c k8 s, |" V: j
void small_init()2 [- A; p) o% j# l1 w6 w
{6 l$ h+ M) Q) ]6 z
unsigned int i, n, len;( w& O/ D/ Q2 K
i = 0;$ C' k( z( V' J8 k, W% K- \, b. z
n = SMALL_MEM_SIZE;$ e8 i6 _* [* l1 U: V, |
9 `0 _+ S7 }+ d/ k
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */) C9 v p7 p" I8 l
SmallMemory[0] = 0x01;
, X5 M# P l2 d F i += 2;% u: ?5 d+ G3 E/ G* m o; Y
n -= 2;
5 J* L( H5 U7 ` T+ |$ q# K }; v* l4 O3 b6 y
3 A- {( p, `' K" E' r7 @0 q$ s
% o0 q- G: A1 m while(n>1){ /* Init Empty Small List */' n0 V6 k u- i- B
len = (128 < n)? 127 : n-2;% ]* q8 Y4 T) c/ L( [" q' v
SmallMemory[ i ] = 0x80 | len;# h: S/ j; C9 d$ B& e! z+ u& x1 M0 R8 b
len++;
5 b+ ^: O& g; X4 W& g; u2 x8 j g* \ i += len;
7 n0 {. v2 T& O3 L/ q n -= len;' l' t7 \! D& T. @! m, B9 ~) `
}
; ^3 p4 U/ S' b' Y. V0 m SmallMemory[ i ] = 0x80; /* End Of Small List */
) U9 Q, y3 o' B) ?6 O$ P) S4 D. X}
9 k' e1 W6 G6 `- B3 s0 R0 @" z! w4 [% O$ |3 C& V) O, w: V
void * small_alloc(unsigned char size)
' e+ _1 ^; x' h: \2 _{
4 e! x: q% c5 f5 P; ` register SMALL_MEM unsigned char *p1, *p2;
: l7 G% U' X- R/ I/ z register unsigned char len;/ v# Q) g% Z* g* U I3 l, {# ~3 L3 b
/ o8 ?- g+ b# t5 O
if( size > 127 || size == 0) return NULL;
4 a7 _& e7 Z g' E0 b9 a5 n3 ~- o- k: W
p1 = SmallMemory;
# w6 Q2 Z f K! H/ u while( *p1 != 0x80 ){
" t. Z, j, K( @: p: w7 G% P* r len = *p1 & 0x7f;
) {1 r% \. J4 u+ r& Y# Y if( *p1 & 0x80 ){ /* 找到空的内存块 */. c! E$ d* I% Z2 r$ V& a
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
$ }5 u* z2 Z& B, R8 \! j p2 = p1+len+1; , C* X7 l U- g
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
2 \& h9 H8 K' ?9 }7 u- Y* v2 H len += (*p2 & 0x7f) + 1;$ @& [6 J( ]: z! M4 Z
}else{5 y# P; o4 M. u# {
break;+ P' W, @* c- M# D6 p7 l
}* ?. W' D) \9 X3 _
}
8 _( J1 A% p+ Q3 w2 [0 ` if( len >= size ){ /* 找到一个足够的内存块 */ `( L& s# c- D: n
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
, C; k& D! J# ~2 ?& r *p1 = size;
( m8 C* X6 d* H) q1 ~' `* ^ p2 = p1+size+1;
* J5 q) u( [) f/ R2 V( A *p2 = (len-size-1) | 0x80;
7 D( l) Z4 g( B/ [ return p1+1; \1 U8 `, o' [
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
3 [" g# U1 Q# d3 k! D *p1 = len;$ I& ~1 c, `& o0 v4 Y
return p1+1;, d- v% @1 u8 b I% w* S; R
}
1 ]. R- j2 c( I) D }" z9 `7 i, e4 s+ `) ^) s
}
+ y# A& `$ O, [6 w4 Z6 T" S! V" A( s p1 += len+1; /* 找下一内存块 */8 t) D% m4 Z1 f- ]
}
$ w, [6 t' [4 c( W6 m" j$ @) r return NULL; /* 没有可用的, 返回 NULL */2 C8 S& C+ k' U: x: k2 }3 ~
}
& k2 g% y; T' r; ^2 \
6 S1 s/ M; j0 K5 V: Hvoid small_free(void *mem)
! L/ q7 n4 }5 K& u: q# J{
4 h/ A! x" F2 k# T; L. S0 Y1 A *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
# D/ z: E4 y; D7 z' z& |4 y" P; ~}. x- \7 A& n' R/ S$ H9 C# T
' U: `! K! R4 P
|
|