|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).5 P$ r& q( D, o; {+ ?
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
+ ]4 M' y& b8 N; n. v5 i正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:0 G4 O# d n7 Z1 q3 P5 q# `# j
1 n( ?' Y' @* m8 i3 _- \9 O
. @# F; B. C5 i9 d4 q3 l仅三个函数:
# ~& X. ~9 N c( h. h6 f
* g# e' ^4 {: W( i7 A4 r<<SmallMem.h>>8 ?. w, ~/ [. U* @
7 s7 v* z9 c8 [# J% p. a: dvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块., z: i$ \0 {, V% J7 t0 ~1 B
: `3 Q9 i1 a0 C
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.9 T1 y+ \9 {5 s6 W6 z
分配成功则返回地址,否则返回NULL. 0 h( ]7 N9 F e
V% Z# O0 G- v% O
void small_free(void*mem); 释放内存块.9 e8 T I, I5 c; [
n' T% @* Q, B6 w) V& @-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------8 g$ a; r c0 N: b0 q: G' M6 Z- j6 o
<<SmallMmem.c >>$ h/ {3 s6 l" l- ?; k
# Z- D- g/ b# l0 J, R/***************************************************************************************************
% L" @6 X$ R+ ]( W3 y3 v! g, | Small Memory Managment ....% u. V% k2 h9 _
Copyright 2008 by David Xie ! u* |6 r0 }& Z8 K; S- Y
7 }- }& X; e- J L* Z6 o) `
Last Change: 2008-10-10. q3 s* |% V7 L3 q7 w
3 R5 C! T7 p! E8 Z( c ListHead Byte: Bit7 = 1 Free Block* Q8 X$ I& Y; h
Bit7 = 0 Used Block- U- |9 z% l$ Z. \; G( p) q
1 N- K& ^3 K. t9 l
Bit[6..0] = 1 - 127 number of bytes of memory block8 c! Z" l* u, N' X
Bit[6..0] = 0 end of memory block! I; L: G! U. s0 E- Z
******************************************************************************************************/
& K' Q) U& x' U6 m
3 U; x# k* G* Z4 n#define SMALL_MEM_SIZE 1024 // 依你的系统来定. y7 z. \- F# ?1 ?* o: E, t$ b
#define SMALL_MEM __xdata // XRAM
& ^( |* E3 e+ ]6 c& X" V% K% z r* f' l: y* S( O" M
//#define SMALL_MEM_SIZE 256! W+ C# k. t$ q7 W; G( u% q2 T
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.* X" E* N& _' S& H0 B4 ?
. x4 @8 {0 m* h' ?3 F+ @" |SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
5 y1 _+ a/ k- E' W
, \9 ?) c! ~! U- u+ ^1 O, v: Ivoid small_init()6 n0 t/ G5 `6 P5 W
{) [0 a# C6 j9 W
unsigned int i, n, len;
2 n, J5 m3 T* K/ I1 l% Z U1 w2 @ i = 0;# \; W$ K& E; o- l
n = SMALL_MEM_SIZE;; {9 e7 R9 w* p4 B
: \4 t, {6 V* B3 e
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */# k T" o& Y- G1 _% q
SmallMemory[0] = 0x01;3 F |5 I: ]8 J! \) T+ u) j
i += 2;8 k; }% c3 N3 n, b! c1 p& ^& {
n -= 2;
# P% L; N2 L) s# ~$ B }
# e+ ]( `0 I0 v) H9 Z
5 h% H1 D: K& t. x& G
" p. ?( m) s- x, Q+ U# j- }$ ?- Q% s while(n>1){ /* Init Empty Small List */
8 P9 C2 s$ C+ ^ n len = (128 < n)? 127 : n-2;. b& u& k$ |# s% w u7 Z- Z7 v
SmallMemory[ i ] = 0x80 | len;
+ ~; @# _( p! \/ k' z& E& L6 } len++;
2 D0 a' R: X4 B i += len;
% z9 B6 f0 [* o2 N" d n -= len;
r+ A! k3 h! r1 {* M! L4 R }
) ?0 H0 p7 Q1 J9 y SmallMemory[ i ] = 0x80; /* End Of Small List */7 P$ H/ S/ ? G0 ?
}' c# E- f/ Z; p/ b" [& t& x d3 p' u) b- t
/ F( ~. Q6 \! M: P0 fvoid * small_alloc(unsigned char size)
5 y3 \; {3 t0 x& S- t( ]{8 U# w: n" m1 ]7 J5 r' E. @
register SMALL_MEM unsigned char *p1, *p2;3 @6 l' X. c- V- _; q# @
register unsigned char len;
" H @1 a, Z0 @5 I, V/ {2 A
8 l- e P8 ]' N/ O" O" l' ^& W! H+ D if( size > 127 || size == 0) return NULL;& R/ n8 H* t+ ?# n% L4 ^7 N
+ H$ R& j m( ]4 |5 M e6 ? V; n p1 = SmallMemory;
) L. p( u" T+ t8 | |' p* p7 e# H ? while( *p1 != 0x80 ){1 o6 V) s0 ~7 f
len = *p1 & 0x7f;' n0 I9 ?, \1 k2 R
if( *p1 & 0x80 ){ /* 找到空的内存块 */
/ x; h& \; v$ q% z" t6 Q while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */3 l5 y) d% H/ d8 C
p2 = p1+len+1;
) J- S: G( u" X if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
! ^+ T, t8 ]# m5 L1 \# E len += (*p2 & 0x7f) + 1;8 G" }4 n& h$ ]+ b/ x) l* ~/ j
}else{
& B" J" G$ d U) G( t9 R/ |6 r' m% ~ break;
1 P: b4 w' ~' v6 E# t- f) @ } L- y# ]. W4 P) N; C
}
# O% f" W8 h" J# ^ if( len >= size ){ /* 找到一个足够的内存块 */
$ I1 a2 d2 }& k( g if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */: _8 j. d7 k1 n- M7 p! n
*p1 = size;
0 }! }6 {# w" V. M p2 = p1+size+1;7 I, D8 q- m, m+ t
*p2 = (len-size-1) | 0x80;5 } ]) Q; b- N8 k# }3 {7 y
return p1+1;
0 s1 T1 _0 I# L" ~: M }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
: l6 R! r4 h7 Y) q$ j+ } *p1 = len;
5 O0 L7 v: ]' @ return p1+1;) l3 P0 J6 n/ t# O
}/ C9 @" L# N$ V
}5 [7 w/ |) I4 H% e4 [1 s' Q2 ]
}
5 e7 V8 @& U+ ^! b) G. v& e% B p1 += len+1; /* 找下一内存块 */& g r" M5 h5 e! k) S1 K6 O
}- N. D: M4 M0 _2 Q c
return NULL; /* 没有可用的, 返回 NULL */+ y& ?9 B [7 U, q2 ]7 i0 q2 Q
}0 a' z4 W [& d7 N7 R
$ c$ U, {$ B+ |
void small_free(void *mem); B$ A3 x, m- L+ R& t& p
{; l& l4 X i4 ]
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
: ? y/ y, i/ t}0 _+ M9 X8 Y" y1 m2 C0 ~
1 @7 r+ i9 y0 z( `$ p$ m- k6 a |
|