|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).$ ^% y8 P1 X0 U, B( |, F+ I
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
5 F, @2 }2 N3 d) y8 ]- |6 `% h1 p) }正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
" {1 u- j0 K, t7 h3 S( t
% g U Z" G; Z4 o/ [& L f: ~7 o& z6 t0 n
仅三个函数:
8 F& C5 [, s% r" s
: l& m; z4 x) U" E, a<<SmallMem.h>>
0 ]5 U, j/ }. X3 e% U& F/ b9 v
3 s) `9 }0 |; b6 Vvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.* G5 Y, d/ E. ]; x) l
, O. [: T9 Q, W4 k4 y4 Q7 J
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.# G, ~$ K/ ~; M8 T& A
分配成功则返回地址,否则返回NULL. ' x9 N3 d0 \4 {+ y
8 F) u, Q+ t1 H0 i* X- Evoid small_free(void*mem); 释放内存块.
0 w- \/ R* L4 c6 n! `/ t. X. }" M- H+ ]5 n" I: ]* K8 R9 X0 C
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
k4 C9 h6 }/ D, R- S<<SmallMmem.c >>
9 J; R$ i% l$ q4 X0 D' p# z
2 p. L7 w0 U, S3 V* y& q/***************************************************************************************************
$ k5 ?- ~" X/ K1 [! d1 w" P; \" e Small Memory Managment ....
. _5 `8 [, L; F. c' {$ R# W Copyright 2008 by David Xie
6 K9 W1 a; q$ ?" r8 z0 j* M5 j% N) ]6 h- c
Last Change: 2008-10-109 _3 g* U4 ^! K
8 P8 A! \- P! O* w ListHead Byte: Bit7 = 1 Free Block
5 r. d3 v/ d' K3 E Bit7 = 0 Used Block
v! {/ ^* j$ t7 n" s- T, s6 \* u/ U8 t. E6 C
Bit[6..0] = 1 - 127 number of bytes of memory block
" V' W( o% O, ?$ K+ O5 n Bit[6..0] = 0 end of memory block
1 h( O L) _; a9 P******************************************************************************************************/9 z: k* b4 J& Z
: S0 ]1 C1 k7 h+ X# C! F+ _#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
# ?4 ?$ S* s: _' Z/ x/ I3 \#define SMALL_MEM __xdata // XRAM
4 D. p5 D6 P: {" _ A( u" \0 C' r; _. `+ I# f+ X
//#define SMALL_MEM_SIZE 256! J5 T6 \. ]* l0 ~. `6 @' K. U, S
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.9 K' I" m. v4 P. _
# S- d. O( v% V+ Z4 Q6 H% gSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
; V& V( Q# Z3 b4 M5 V
" b: s; G, {6 a4 _; p. u/ X% Yvoid small_init()
( T3 ~# q. K- v- W{
1 m' ~/ [: ]: u. {9 Q! f unsigned int i, n, len;+ s5 y0 h; n" n
i = 0;. f0 e5 c; u8 f. q# _; ]' I* B
n = SMALL_MEM_SIZE;
2 h1 Z8 p1 `* R4 E8 l: @
7 l3 K( c8 e* {4 }% H' a if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
" P2 L9 A0 k% b7 t( N/ q; S SmallMemory[0] = 0x01;
; Z8 N$ a" P5 A K! {4 Q i += 2;
* s8 [* B4 D1 Y7 W$ ~! j+ \* b3 N n -= 2;) c3 [; c0 U6 x" w4 ~5 n+ }
}
0 p! w* h5 W# g8 P
+ j2 K- Y' j4 z# k* y. M
* W) |1 K" k" d4 G! N( {& s4 S while(n>1){ /* Init Empty Small List */! n7 c. _' G2 X2 b2 { f; |
len = (128 < n)? 127 : n-2;
$ W1 V- _; V& d0 A( D3 @ SmallMemory[ i ] = 0x80 | len;
8 l0 S% }' u7 C% g4 l. ^ len++;/ L: `' O* [# R( ]0 E4 Y$ Y4 R
i += len;4 x# W5 q' S8 e7 H _" V- B
n -= len;, {+ K+ E+ o0 @; u+ D a
}0 G, s* }, e$ G8 |. x+ Q
SmallMemory[ i ] = 0x80; /* End Of Small List */* s- I' O. E! [% \; ~; J, p
}
; Z/ G G5 H# R& o" O! \& W0 b/ w8 m: c% |% P9 k; x
void * small_alloc(unsigned char size)$ i& F) K! \8 m' V4 V% X
{
; I; \+ w( {* W u register SMALL_MEM unsigned char *p1, *p2;5 I( |. v- N6 Q" \3 \4 F
register unsigned char len;
' V- D4 E9 ?- ~4 C0 X- t% u0 b' R4 p8 Z; L
if( size > 127 || size == 0) return NULL; n9 `2 S9 y* [6 N8 D7 q
) w+ u: H D/ T1 m2 W1 E7 y
p1 = SmallMemory;
! F7 R* H9 b6 d4 p! t while( *p1 != 0x80 ){& {4 H, T& e1 F/ z8 p1 i: q9 C9 i; }
len = *p1 & 0x7f;; h2 C+ o9 w2 O8 ^& H) ~% x l$ K T
if( *p1 & 0x80 ){ /* 找到空的内存块 */* L" D' `/ E$ p: m3 [6 N0 g' M
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
, M+ ^" _ p/ r( p4 U' R p2 = p1+len+1;
' L' |9 A. {& v" T' I1 u- Q if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
1 ~' \% p1 b" z" r# C len += (*p2 & 0x7f) + 1;8 F/ x8 s$ S9 G. x3 P
}else{' g9 w6 ^, J2 ?7 E, [, w: b; C
break;
! w! ~0 \- U$ t( N+ ^ m- G! M }& z: X6 g0 s- `9 k
}6 I7 @' K, a) n9 A. B5 ~3 z
if( len >= size ){ /* 找到一个足够的内存块 */& v* r4 k$ {3 ?& K$ }' z
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */$ O" u9 {1 |. B5 j& H4 m J6 ~% f( q
*p1 = size;( V) q! r5 \4 |9 ]- y' S$ ]1 g
p2 = p1+size+1;- g/ x. x" P. T" g' j6 R
*p2 = (len-size-1) | 0x80;
/ D. t) i/ f$ E, ]: s3 A return p1+1;. W: H$ `3 a1 Y4 M( [' a( @
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
1 i* c2 r& C1 d+ j5 A# B1 K# c2 r *p1 = len;
/ H' P' s8 P* A) j7 ~) a. B return p1+1;, O( E* R5 ~0 A9 f! Q, J
}
; ^# `8 w3 a4 |% J$ F P }
/ @8 }: T( d @7 {1 x }( W1 v% u! A! U w9 _
p1 += len+1; /* 找下一内存块 */
: j2 G* S) N. V1 a2 C# M }
! [2 X6 A) l3 x8 f return NULL; /* 没有可用的, 返回 NULL */( P: B4 W( d1 O5 h; _6 P1 y, {
}8 n; M; R; Q) K
% H# d8 D7 E7 b8 W* ^void small_free(void *mem)# y$ C; w+ o: w( i
{' \: a6 Q- W3 r! H' u& J% g9 S
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */2 s! E$ P6 w% T1 V7 ?
}
! L0 r9 Q- w5 ~, L
! p& ?+ _% N& G* r, g9 [; I |
|