|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).8 p1 Q) ]+ Z0 n; B- m8 j
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
7 E' P. w2 |: e# F7 F0 ~4 E6 W正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:" H" h0 e2 O" M5 z
3 U0 w$ {& N0 u7 \2 G- }$ q+ L' g
8 S- f. E+ t0 ~- T+ E0 L8 ^仅三个函数:9 }9 @0 `9 l1 R5 ^2 X
1 O8 R/ W# f3 y; _$ L<<SmallMem.h>>
' D9 b2 S7 o+ R1 u5 @ X L' j1 I5 l2 \( [6 s. l
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块." P; S# x2 T# K
( N# s, K6 G/ Y& e/ Fvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
s8 g, p- b6 [ 分配成功则返回地址,否则返回NULL.
# V- }# y c. [/ h- e J* z7 |0 A) K7 [& R9 A. ] _% g; ?4 E; Q/ N) {" x
void small_free(void*mem); 释放内存块.
& E" z) P0 C0 T3 Z. \ z
; \/ Q( [2 s! f4 N4 t6 W6 E-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------4 u! w! Z) ]& z
<<SmallMmem.c >>
# K5 Y. n8 l$ Z$ B. c3 |9 ~% `5 ` t
' V, M i9 b/ B5 g. @: ~: `% ~0 R/***************************************************************************************************
1 n; h- W- M+ V6 {. i8 { Small Memory Managment ..../ R, k- Q, h, M# v
Copyright 2008 by David Xie
+ o9 `( _- v% R6 ?+ w% o
7 \1 m0 @( Q5 B" y Last Change: 2008-10-101 F! _3 R2 [/ W8 \
% S- W- M8 i' f; f/ `7 I7 ^ ListHead Byte: Bit7 = 1 Free Block- K9 r$ [4 u% R
Bit7 = 0 Used Block2 M. W3 c p+ t. b$ `, F
/ G, x" N W$ N0 ~. }4 J4 J Bit[6..0] = 1 - 127 number of bytes of memory block6 p& F2 [: Y9 i, C- T
Bit[6..0] = 0 end of memory block5 F4 x/ O# t9 {% y- f
******************************************************************************************************/
3 \: D8 u9 w0 w* s
* b' N2 c0 k1 E3 ?/ O#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
. w: f: k0 G5 n2 b#define SMALL_MEM __xdata // XRAM: v+ F* z9 L6 u3 H+ W! P' Z' w4 i
% }$ X+ e$ Z( u& j6 M6 h0 W. a% e
//#define SMALL_MEM_SIZE 256
2 S+ i% K3 e# w' t- V( n//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
% e4 {2 D' [2 P3 W
2 _0 [3 N3 l0 I- p2 @- x& aSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];+ k5 f/ ^* z' @1 x
7 |) t! h$ h. |! D4 e# q
void small_init()& r$ O( s1 Y* X; b; o- \" _5 V
{, ?; I7 c R" D8 I5 o
unsigned int i, n, len;; { T: J$ x9 N2 w$ |4 T) Q0 O9 ~
i = 0;
! x* P) }1 ^4 p% d7 I9 A* e5 O n = SMALL_MEM_SIZE;
) y# r2 Z$ w$ s0 W& r8 x" Y; J# ]; \
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
3 @. R( r: m/ ?! K; Q5 I9 B3 J SmallMemory[0] = 0x01;
& E* m% k. N0 K9 z i += 2;
& t' M% i- |+ C" o9 G" A n -= 2;
9 W T8 `; j4 m0 w }4 U" B9 v2 [$ x v
$ H6 L8 D% L1 Z( X3 r: ~# y
" R+ \, Z1 G5 W
while(n>1){ /* Init Empty Small List */
/ l7 ?" T( m+ x) h: o len = (128 < n)? 127 : n-2;
9 f. p" h4 c d0 {% r) n7 Y SmallMemory[ i ] = 0x80 | len;
+ [0 {3 L( l( z) e: i# A len++;( Y# [( F4 l }
i += len;
( S# D/ M1 g& k: p3 y/ F" n' L# }3 }+ n' h n -= len;+ p3 _5 ^) j: t4 b' Y0 h
}
& a, ~) d( I2 L p SmallMemory[ i ] = 0x80; /* End Of Small List */
- x/ g, g3 r, q}
6 n7 ], b) `( }( ]* u0 ]1 M9 u4 k0 }1 P' X* A2 v+ s& x
void * small_alloc(unsigned char size)
6 A+ y( ~8 r/ g; b: Z, K4 N{
$ A3 _: A; S! ? register SMALL_MEM unsigned char *p1, *p2;! i; [% l8 G. R% t2 R. R
register unsigned char len;9 p' [9 T: ?: c( l1 C
& K" F6 q$ n7 J& N if( size > 127 || size == 0) return NULL;* K( I4 e5 ^& u
2 t/ [$ Z7 Q7 r
p1 = SmallMemory;" b7 c7 ~ Q: Q' Y' A6 U
while( *p1 != 0x80 ){
: K3 X- r, `+ a3 i( @/ ~ len = *p1 & 0x7f;$ q1 `2 X/ z7 }( x% `0 s0 _
if( *p1 & 0x80 ){ /* 找到空的内存块 */
. ^' i; c. w1 } while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */$ F. q6 c( ]+ p4 g3 Y% e( I* G
p2 = p1+len+1;
5 f u- Y U$ P w. i# U) U if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */0 `0 w& {# f0 b4 R' U1 O; E
len += (*p2 & 0x7f) + 1;
% m( B" b, w5 C' a }else{7 S( ^4 v8 o- S* B1 U6 O
break;& j/ z+ x' m& V% U
}+ }3 M+ I, w! y# ]% T5 \
}
# P3 b2 U3 y+ j* j: x9 E$ r if( len >= size ){ /* 找到一个足够的内存块 */- N. O5 C: B+ V* U
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
; M$ f c1 F+ A0 ~& e *p1 = size;# r9 c3 @% `: D& W" X6 P# i7 R; N/ ~
p2 = p1+size+1;; b- O% ?8 |$ K0 l
*p2 = (len-size-1) | 0x80;
F9 |0 Q0 a1 ^: ?* u1 v return p1+1;
0 l, [/ e/ b5 [- k }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */7 ]5 X. |' { I4 @ m) M% n% Q. y. e
*p1 = len;
3 t' @0 l. U2 Q. ]+ e return p1+1;
6 D# [' W( u3 x+ r |" T ~ }
3 D' ?( h& s/ q/ ?( Z) s1 V, s, I }$ n3 T* f+ P i# J' p; x! T: H
}3 ]. {+ Y8 k4 k
p1 += len+1; /* 找下一内存块 */
' [* A6 R9 \# \ }: m9 O5 F& i$ @: t$ ]4 k
return NULL; /* 没有可用的, 返回 NULL */
( C9 Z; k) i: i2 M}
3 I" h% y. [' N( B
1 V* X0 M. u1 q0 ^! D. avoid small_free(void *mem)
' T3 Y+ F( Z6 X2 C6 ~{- O" O( O& j m( P
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
' ^, W* X/ `( `7 k( g1 O" H}
3 R2 c! E3 J) i9 b! X
0 m* I4 ?/ z2 v9 D |
|