|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
7 \& P3 f0 e3 Q& i. b因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
: \( @4 D5 p, C( v" X" M正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
?: g/ n4 x; @) g! y) ^& y- t$ p1 T
! H& i7 q/ j& u+ L( J& o7 ^
, s6 P$ C7 W/ I3 I1 M仅三个函数:# @! z3 Z' z$ O; w% D3 t' N
8 d5 o- G+ {; F' R
<<SmallMem.h>>, k2 p/ p$ e) @* A n) ~, e
# D$ M* V5 q! r9 {; h, ~$ uvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块. p" }; N3 t3 c1 t
) G! N Y! z) w5 W6 B, p2 c, avoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.. C6 T$ x4 ]- p2 s5 x
分配成功则返回地址,否则返回NULL.
* j* r* Y1 M$ `& f: B5 W$ \0 D5 K6 h4 U3 U
void small_free(void*mem); 释放内存块.
% y3 o+ {& C% Z
& v: _' y" d3 h [* E2 x8 a-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6 z( X3 E6 N# @+ X7 F<<SmallMmem.c >>, A) W: [0 {4 b d' N
9 e& _' S2 N6 B3 x/***************************************************************************************************4 P* @% X: ]" C/ f/ ?3 ^
Small Memory Managment ....
4 N% ?! k; b" n1 l Copyright 2008 by David Xie
# u9 H& n. q8 W* k& M4 d' g- v: x( |
$ H3 H3 [1 d) Z( h1 ]# u Last Change: 2008-10-10
% r: X7 n" z4 x6 G2 j- }+ @" f; ^8 g
ListHead Byte: Bit7 = 1 Free Block
, K. y8 N+ W+ ?+ N' n" G% \ Bit7 = 0 Used Block
' I! Q* v/ W- U0 ^5 H8 @. c+ }. q1 i5 O
Bit[6..0] = 1 - 127 number of bytes of memory block. } `; _; Q. y0 p
Bit[6..0] = 0 end of memory block2 u* Z7 \9 J' I8 _4 ~" C8 ?
******************************************************************************************************/
0 t) c. }/ f' h4 ?, E6 ^& d
- _ @7 w: U; |# ]( d#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
, c$ }. I8 E$ l$ w+ ~ Q#define SMALL_MEM __xdata // XRAM
$ ~; m) C0 m+ e! z, y/ m: |# l) J, ]. U9 S: J0 H
//#define SMALL_MEM_SIZE 256- w/ n( [8 }% T2 e
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.0 u# }$ e; D9 _) G1 z2 M0 Y
( ?0 X) \1 }; w; |
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];: G E3 Q3 D6 I: B5 V# v
6 ]' `, J. e j' p; [' W# G3 Avoid small_init()/ r2 D9 }7 O1 T8 h. u, X
{* @* E% l$ v/ n9 ?
unsigned int i, n, len;6 e/ O; d: y5 p, g8 z
i = 0;$ x! A. B: F8 Q8 k+ ?6 z2 {
n = SMALL_MEM_SIZE;6 ]1 J6 |, ]" S- M9 W E0 M
& m+ |- G! {6 Y
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
6 X' y7 b: Y2 O w SmallMemory[0] = 0x01;* r' d9 S5 x7 G
i += 2;
t* z6 _& P2 I+ T n -= 2;
K7 z: q1 G3 r* g2 m0 M1 d4 d: { }
( {9 B; d$ A* @8 C: v& O, [7 t7 {1 ]5 H$ k2 [7 W
3 U# W/ E8 D. @9 F u
while(n>1){ /* Init Empty Small List */3 U* e& E' Z& r6 t
len = (128 < n)? 127 : n-2;
7 q+ m$ _6 a: u SmallMemory[ i ] = 0x80 | len;
% b, ?! _- j F$ \ len++;3 N) |: G% A* K
i += len;
w" e# K `7 A) y) d2 H n -= len;7 g* L3 k9 G0 @6 j( I6 u5 @8 e
}
2 C/ d) b! Q) w/ S SmallMemory[ i ] = 0x80; /* End Of Small List */
8 V/ q$ P" k0 ~}
O! D6 r' [. V6 r
3 `3 P* I1 k: ^" ivoid * small_alloc(unsigned char size)
0 q8 d2 e f% V+ |1 _6 V! Y{
8 N' U1 v: a9 y0 `- n4 I0 F9 { register SMALL_MEM unsigned char *p1, *p2;
6 N; y8 M% Y$ B3 f, X, s: y" T" F register unsigned char len;
6 j* z8 k% \/ P( ^- F9 K) ]% R3 h8 H! O# P& w. O2 v
if( size > 127 || size == 0) return NULL;
3 H; Q9 n6 Q6 z- N: [2 P# J/ f* D# X2 F( q5 m. {
p1 = SmallMemory;
$ ^. ?; n+ J8 O& b q. Q" @ h$ m while( *p1 != 0x80 ){
, \4 Y8 H. ]0 I+ m len = *p1 & 0x7f;
( x1 u. G3 W- {. u+ i6 c6 r: O$ r( e if( *p1 & 0x80 ){ /* 找到空的内存块 */
6 k) i9 k3 G+ w3 N while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
9 I9 C d' [$ w+ }% e p2 = p1+len+1; 6 i; P; ^1 G# x5 t1 P( s% v% {# x
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
7 K! t" j2 }$ ?( b, x: v: p' R6 F len += (*p2 & 0x7f) + 1;/ f. N1 I( ], i( \/ X- i6 D/ m
}else{
3 |7 W8 g* ~6 H6 {; X0 F! ] break;: F' p' X3 b" O( T& F
}
0 t( Y( O$ ]4 ?. }" b }6 ^- p/ B1 w9 D0 Z. I- b6 B9 _
if( len >= size ){ /* 找到一个足够的内存块 */
j/ {- P% U* R, H if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
2 Z- h, ]" r( `) n. [! \ i, f# o" b *p1 = size;& O% m8 s: s, ]
p2 = p1+size+1;
# |; b, @, Q# `% Z, F8 a* U *p2 = (len-size-1) | 0x80;
; X/ U5 E4 y, E/ q4 _ return p1+1;; g" ^% p4 o0 k @
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */4 }9 A2 z) L( b$ R( ?' \7 X
*p1 = len;1 E+ _( S0 ?1 t; @
return p1+1;
1 z% A! z. T* Z ~; s! x/ L) Y }
+ s0 b4 W! q; h2 t: ~6 j* d }# c S7 c; b4 S8 O# `4 @8 l) _/ B
}8 z3 G2 i- L3 ?
p1 += len+1; /* 找下一内存块 */7 C: J* W4 |8 F
}4 A2 h; i0 ~& N4 O% Z
return NULL; /* 没有可用的, 返回 NULL */
" b6 ~* n& j7 w g" d9 _, @" N}" `% X( g4 [& ]* c* J% [
( d% N# Q+ L1 ?; |# X! M, T$ mvoid small_free(void *mem)/ P6 l9 h7 D* Z
{" _3 v5 n7 V d7 S" V+ X
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
7 d+ U: g6 l0 ~$ t W}3 J% _1 ~, M2 z: b# F
4 O! w3 z- P1 k1 [
|
|