|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了)., `8 j+ l5 [) O# f8 [
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.# n' U7 U3 m4 A4 o( N
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:. O+ l; N" j' B5 u. E
1 t" g @0 B( ]8 Z" ^4 \, N
7 _! P) `# T8 I5 T' N
仅三个函数: x& |% z: f1 e
! F- G+ C8 D' o f7 p5 t& e
<<SmallMem.h>>
1 f) b* N7 o, y- @6 i
# [; Y: M S, C$ n) ^void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.% g) u) D( v) j/ A# g, ?
A- m3 x' P6 J( U- X* H' v
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.% p4 y+ ^0 l3 A
分配成功则返回地址,否则返回NULL. 6 H/ I! E5 H' d$ T- S7 f
; u1 \ C0 [2 n: @) c- p3 Y. ovoid small_free(void*mem); 释放内存块.$ l6 |5 ]* l8 [% l* m
( C8 C& V8 G( |' ?* c: C+ J-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------8 g# e' Z" g& B. l2 g3 o
<<SmallMmem.c >>
- k# n- C( a, E, c# |: L+ C
* j) M7 ~0 r8 R. h: m/***************************************************************************************************
4 O% ` g* c* O. n& H8 V Small Memory Managment ....
8 g# }: s3 J [ Copyright 2008 by David Xie 8 b- t% V! B' O& g
1 T# ~3 A( b, ]1 E! X6 @
Last Change: 2008-10-103 j# \& _( ~9 X# u8 O* d, ^
5 B" D$ `3 R2 C, A3 H2 F$ J* u' F
ListHead Byte: Bit7 = 1 Free Block: b& @8 [/ u+ q5 v
Bit7 = 0 Used Block
& X$ q+ T y2 c6 y$ v2 U5 a Z" @! E5 [1 `% i" l
Bit[6..0] = 1 - 127 number of bytes of memory block0 E: ~1 o. j1 o( o: K4 J
Bit[6..0] = 0 end of memory block; N* L* I* W8 b8 }; T9 f0 Y
******************************************************************************************************/* t0 M8 R# X5 V+ N/ c. A; f# t
& O2 c/ R" m" X# H0 j9 m
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
6 t: t, Y7 B- L( F#define SMALL_MEM __xdata // XRAM
! M6 V2 v( Z( m! g4 O* ?# r6 @$ T4 \; |5 b( x& W; K# U2 ^* k. V* f7 K; X
//#define SMALL_MEM_SIZE 256
5 `+ c# Z8 X8 C/ _( u//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
$ G) K2 X/ U, |7 V) b
5 b/ n8 x' F3 o! ZSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];+ O; z" D0 R8 r
) {! f0 U7 d$ L' Q7 m6 F( P1 G
void small_init(), E9 ?% ?, s; o) G
{: }; c k' |4 k% x0 q. j' h' L
unsigned int i, n, len;
# y# l# y% z1 d8 [, i) t i = 0;' u1 t" r, h) a1 z( Q% `0 ?
n = SMALL_MEM_SIZE;5 l( J- B( |1 k# g; e
; J7 L y1 d- O if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */# b( J: h: b* Q4 x
SmallMemory[0] = 0x01;
; s1 M+ V4 j* e% }; g; ? i += 2;9 Z/ K4 }% Q7 p! ] y, W
n -= 2;
* p' Q9 X2 g1 R0 s% U0 E }
7 i6 D0 m$ x) ~! m- b
T: \; R- E5 u$ ^' f
1 Y2 R. ~# W& @1 U3 r while(n>1){ /* Init Empty Small List */ m8 f3 ~; ]- [5 o x6 y5 x; y
len = (128 < n)? 127 : n-2;
0 A5 F- ^5 H$ {9 P SmallMemory[ i ] = 0x80 | len;' t, D% U8 @ m' z2 O3 F0 w9 e
len++;* R6 ~- |5 E3 v1 Q3 N$ G) P0 z. z
i += len;
6 z/ d" N* v. w; ?5 ~ n -= len;
: d1 r) }' G, c+ x9 ?7 C& S }
; z4 p2 I/ \+ o SmallMemory[ i ] = 0x80; /* End Of Small List */9 J* W8 m8 k" n
}
, K$ T. o+ p) |
6 C& C% W' ~/ b& y9 Cvoid * small_alloc(unsigned char size)
, ]; V% V- W6 C# `0 s$ t7 }+ e{
/ C' r; X' n4 n: k0 k register SMALL_MEM unsigned char *p1, *p2;5 Q: D! l/ s3 M3 E
register unsigned char len;
& k4 J$ k; m4 {+ C0 z# J/ L) T V+ D q' @3 B4 f0 L/ o1 ^8 u( _
if( size > 127 || size == 0) return NULL;
! ^+ U) \; I# x) @4 Z: e# h& _
& c% m8 |. ~4 u! h- z p1 = SmallMemory;
% o+ ~5 `! x# M5 b while( *p1 != 0x80 ){6 h; Y- v7 v n: j
len = *p1 & 0x7f;; z2 d. V1 Z$ l6 H L% ^; r3 ~
if( *p1 & 0x80 ){ /* 找到空的内存块 */ X! n/ Q) P& T. s
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
& V4 s6 P. a* v$ u p2 = p1+len+1; ; _, ]; U! e- V3 j$ a' E
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */5 Q# U- E2 f; Q% @) z* Z
len += (*p2 & 0x7f) + 1;4 ^ ^8 y3 n( X1 U D$ Q p
}else{1 f; V- A# d, |- e
break;
4 n2 r5 c4 M1 P* Z' } }
/ v' `, }9 j4 s7 ? }: d; {! x) ]9 n2 k3 l0 G
if( len >= size ){ /* 找到一个足够的内存块 */" N% D) @+ }% }3 B5 N; b) s
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
* N/ C& j D/ f6 d *p1 = size;
5 ?3 I% H( ^% r+ Z" q# T p2 = p1+size+1;5 f* l8 I& V! \8 l w D
*p2 = (len-size-1) | 0x80;
6 f! L0 Q: N; `. }# {1 u# n2 w return p1+1;
! e/ }* Y6 { q/ A+ D( B* F+ I0 q }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
* q2 o( V3 R$ B A K *p1 = len;9 N' M U4 T3 |' V) _* _% ^
return p1+1;
: Z9 _2 E% ^1 d }7 P+ h4 j* b' Q+ @7 h" b/ |, P& p* V
}
& u, n, `) n! \/ |8 n+ ? }
% @4 p" S) u7 _* i p1 += len+1; /* 找下一内存块 */+ S# M) w' m5 x8 M
}! }/ K' s$ n3 H: m3 j' D
return NULL; /* 没有可用的, 返回 NULL */
( d- b# B6 [& B* @}
4 a6 X0 `5 |! y- l/ y s1 B: l
void small_free(void *mem)
+ W3 P3 ~: ?, \{
( {+ }+ O6 b' X2 [$ a) v0 n *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
5 J) A5 M7 S8 P9 t j: R& b}
# w- l+ ^3 g# I
4 G9 Z# ^7 O3 @$ f8 X! U6 }1 S |
|