|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
b0 _8 }/ [; M3 Y7 ]因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.- T0 q; F& J% ?
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:+ ?1 p3 ?5 v/ g5 `
/ k% H3 K# X. z1 I% H! j4 ]; c7 ~
9 _& T# Y% ~6 L) G仅三个函数:
+ f5 X3 e9 V" [! p" C( B" X* d
# @% G) C4 g" f/ o0 ^. m- C<<SmallMem.h>>' a ]5 n- o( s x0 ~
6 n. p8 q# O" ^% m( t% c
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
! N. X$ b6 l8 d7 w# X+ p& E9 a9 }6 `1 o4 l7 T0 j& c
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
4 F' F) z! a. h* F! X; H1 A _ 分配成功则返回地址,否则返回NULL.
/ o! m& f: l2 [' i. c. U+ B% [& s8 V, G8 |% s5 m. m, b
void small_free(void*mem); 释放内存块./ h: ~( a( ]6 t* \! Q9 J n
! p; `, u9 z5 l. ` z! o) A------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ `7 m7 J0 X$ c7 p' }
<<SmallMmem.c >>
! w; D% t/ c3 c( h& ]- B7 {! W" s' _5 B( T: O8 j9 H" Z# J2 y
/***************************************************************************************************
* F( r! t5 Q; T% C Small Memory Managment ...., g/ p/ [9 P4 P6 ~2 a0 I! `8 a* X
Copyright 2008 by David Xie
6 ?* f# o0 W/ Z- ^6 s
& N5 ?( Q; H0 I; {( w- S( H Last Change: 2008-10-10' q9 A( h% q( B) e- S( A' d
+ O% _! s- j2 F _
ListHead Byte: Bit7 = 1 Free Block
$ o1 d) }) Q3 i; O" e, \$ x$ Q: e Bit7 = 0 Used Block
4 h! c Z& Z/ d1 w5 k* g
% l, a2 l' c/ | Bit[6..0] = 1 - 127 number of bytes of memory block
% R+ `: { s* X6 w8 B, c( x Bit[6..0] = 0 end of memory block$ U) N: Y+ }0 r+ ?3 U
******************************************************************************************************/
4 s/ Q; c; w* S% j$ p/ ?
# z0 G0 C" W+ O& f; x9 [#define SMALL_MEM_SIZE 1024 // 依你的系统来定.0 V! y7 p$ s9 O- `/ L
#define SMALL_MEM __xdata // XRAM* a5 L/ v) g3 L- I1 x
( M4 d S5 ]8 i1 ?//#define SMALL_MEM_SIZE 2566 \3 M/ F9 r9 ?. @: ]
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
2 x* s6 j6 r3 n7 m8 c# O7 K- G8 G2 i# F9 m: C, e9 L
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
* H3 D8 f2 E X1 q1 l
% X/ U+ h3 p3 X; Pvoid small_init()) ]; S8 H' R4 l
{
% }6 r- N( L; z1 {3 D unsigned int i, n, len;
$ A9 L2 D/ l/ J8 O i = 0;# P$ T$ c1 P4 o7 D9 g
n = SMALL_MEM_SIZE;
6 a3 h1 @( D- |& c; y& F8 Y/ T% H0 C
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */8 n6 o1 Z4 s% J! ^
SmallMemory[0] = 0x01;
9 B2 g. a& e! E" I: l% r) O7 Z i += 2;
" _# q; { _( o9 m n -= 2;! B7 ]! p1 K& l; k1 y& V
}% ^+ ], z, }9 F: o" d
- C5 [4 _/ t8 x7 S5 D
9 u. p5 P1 @2 R( i# p) F8 }! N5 ? while(n>1){ /* Init Empty Small List */
4 p; |/ z7 H3 L% b len = (128 < n)? 127 : n-2;& K/ k. T$ E& N* p
SmallMemory[ i ] = 0x80 | len;
% M6 [0 Q% ?* N& e9 b" f5 n len++;
# D9 j& K2 j% G4 m4 b5 P i += len;7 z5 Q8 O! ^4 O9 F s* i. \
n -= len;( `! c7 r; U; C% B: L2 ^; f
}
" S0 H2 r# A2 P( M SmallMemory[ i ] = 0x80; /* End Of Small List */
1 Q3 R: z- X# ]3 L) x( W}
- ~: u4 N ]! o- z
' Y6 y: @( r* b1 `- rvoid * small_alloc(unsigned char size)) N7 n, d# f4 k" T: D
{* g {6 I% F3 m0 L" U9 Z( Z
register SMALL_MEM unsigned char *p1, *p2;
3 |# m' v ]( w0 G register unsigned char len;7 V a; o$ a* H& K( |% e
& `/ {, p4 l6 F8 ^* j if( size > 127 || size == 0) return NULL;: n8 L, p7 P9 }- [# E- F3 E
; I7 ~" n. U7 Q1 |7 `
p1 = SmallMemory;
5 F& T& \! S2 b; _: M- ]* ~ while( *p1 != 0x80 ){
# w% D; v( T$ N len = *p1 & 0x7f;8 B, N8 r9 ^% Y* ^& j2 r* V
if( *p1 & 0x80 ){ /* 找到空的内存块 */7 k" }, _1 M" D* x7 y* {# L2 H
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
8 V$ i9 P8 o# |: o( B) a( S+ E% a p2 = p1+len+1;
; N, o, b# w! n/ s* i+ ~ if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
' d% s |! s4 Z U len += (*p2 & 0x7f) + 1;9 }/ Q# i5 B2 R& P% ?9 x J
}else{$ Y/ f) W6 C/ s! K/ e! \) X, V8 `
break;8 M! j" W' k3 R" [! A' B7 O) v# U, d
}4 I7 _8 f$ ~0 l' ?
}, h! @! H. k* W& A, C/ h0 E
if( len >= size ){ /* 找到一个足够的内存块 */0 |1 A) L g6 r6 q
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
" h; X" L3 V5 B }8 z *p1 = size;
9 C/ E% v! F0 O- S6 _* u0 h4 e3 } p2 = p1+size+1;$ {- Z& i9 X) G; w+ X
*p2 = (len-size-1) | 0x80;
) v1 X6 p" u* t$ K6 X6 f: n+ @ return p1+1;' K( W8 ^; w1 J- M& T" r# p
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
- O- H4 P" A6 }- a *p1 = len;
; v; v6 R! ]7 U, x return p1+1;* A. O0 I' c/ S6 ~6 q3 r1 A& z
}
' z0 b7 }5 W3 C1 f6 k* ^ }6 |1 i& o2 Z8 A1 J/ @9 w: e
}
! G# ^5 P. W6 J3 f2 I3 w- s5 j p1 += len+1; /* 找下一内存块 */# \4 V- [6 _. x2 x0 \* K) m; ~/ M
}" r7 D' j5 z: D6 w
return NULL; /* 没有可用的, 返回 NULL */
- r8 x) J c. M7 r/ j}
. N M* Y, Q' w: H# a! \. Y; s- A
void small_free(void *mem)% d0 M- H+ P1 l$ l. b5 ~0 ~& y
{! n g2 N4 {* X! s
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
5 p9 Y5 z* P% w9 c4 r} C2 b5 i' D g, y- t" i: c
' O3 c, u- b8 \" [8 ^! B |
|