|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).. x- j6 y: ^) v
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
8 p, w6 G' K& Z, [, @+ N+ \正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:) J: z6 O- E* G9 H6 A- w8 L/ }
8 O2 `8 P8 h" L7 Q# O( e
?+ J9 t8 w" O$ `仅三个函数:
' j7 T# w7 K% Z; O3 h6 r4 w3 J, N. f- U; N3 C/ v/ c
<<SmallMem.h>>2 I" ~8 X0 h) W0 K: t$ G3 M- p3 V5 w
6 A- T" t8 G1 [% x0 `% h
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
6 x& x! w! G7 A( G7 q; C4 G$ l* b! _* m
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
8 C6 I8 r" D9 Q! Z* ~8 b l 分配成功则返回地址,否则返回NULL. $ L0 G; @% X1 ]
$ i {( \$ k4 g( m2 V; u V/ uvoid small_free(void*mem); 释放内存块.6 B7 J. \& W* B) ~% v6 u l5 T8 S
; J; J) A* E$ `-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
$ h1 A$ X. z9 b" l+ Z8 z0 Y<<SmallMmem.c >>
0 h. t0 I+ g8 P, k2 ^+ C. W5 O6 |4 u0 Q; I6 |/ Z; [2 ~
/***************************************************************************************************! d$ {+ Z$ \4 u9 H9 Q/ L. ^
Small Memory Managment ....
; s/ f# E; | i% _' N. j1 h9 [ Copyright 2008 by David Xie
+ R) b( g) O* @, d0 D5 q6 X$ K
* q, r* s8 `3 L4 j) _ Last Change: 2008-10-101 _2 \! j9 e( `4 M' e
$ z) m8 U. A, y( N4 b; V5 ]; M
ListHead Byte: Bit7 = 1 Free Block
# p4 K0 f9 a: r Bit7 = 0 Used Block( f8 x/ x, ~4 C8 b
' O P. u4 s7 p, O Bit[6..0] = 1 - 127 number of bytes of memory block
3 @( L2 H% R+ r) b) v& T7 D8 X8 \# O ? Bit[6..0] = 0 end of memory block
; J; @4 [4 }2 z, n9 P# ^% x******************************************************************************************************/5 O4 r9 ?! a# V) }* V5 X1 a$ T
" X! u, T$ U C. d! p y* `" p7 m#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
2 J0 ~ n7 ?0 C& P2 H+ G5 V#define SMALL_MEM __xdata // XRAM3 C8 l6 L/ K# q+ j2 {7 b# l# j0 X
; l# }4 p% W$ O//#define SMALL_MEM_SIZE 256
: r" `' R# E' T/ d1 B |, V//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
6 r/ e0 b9 s4 h- @" m7 B
* g5 u* Z6 |) O$ `+ ^SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];. h T; v' j: q& v2 i' L% T
0 G% T$ B4 Y5 b/ Q: j
void small_init()
. Z5 l3 F- |& w" s{$ G" c' z& j) ~' g+ j
unsigned int i, n, len;; i$ t1 e8 U4 k" C- d7 s7 }
i = 0;
! y, W* O6 t" V( m4 h' V3 ] n = SMALL_MEM_SIZE;
. N& ]" ~$ l7 C( f8 t4 o h6 f/ N: l9 c
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */. \7 g' Q n( R. \# h. I6 y- I
SmallMemory[0] = 0x01;- U/ C# o w0 r1 A5 i. j6 C6 x, g
i += 2;
" \1 g k- I( ?! j# @3 q n -= 2;
2 U; {' z' Q$ ^3 @, b8 y+ L/ { } p v$ v9 ^+ T3 L8 {: W& ]$ g
; Y: q& {" }6 }% u+ w7 p+ f+ R/ \: P
while(n>1){ /* Init Empty Small List */3 E8 _9 Z1 k) x9 B3 S$ k
len = (128 < n)? 127 : n-2;
8 |0 f8 t+ T/ Y5 y. G& ?; Z SmallMemory[ i ] = 0x80 | len;
! m( n2 q9 Y, B d len++;2 i* P. b0 a% @- e6 U3 S/ f2 c
i += len;1 ` v$ ~% B% _2 F$ B
n -= len;
0 ]; m% X. Z c3 S4 m }4 C4 ^3 a/ o0 l/ |
SmallMemory[ i ] = 0x80; /* End Of Small List */
' r5 T. y% m0 f) Y# T! q. Z) X}
5 @2 R- B3 n: e/ }5 h' |$ O
; \; L" ~* i1 m3 ?void * small_alloc(unsigned char size)
* `6 P3 _4 r. O6 J K0 P{" _' @* U( Y1 s; t' r [! a3 y/ b
register SMALL_MEM unsigned char *p1, *p2;
/ k4 l2 y$ S4 R$ ` register unsigned char len;
4 V# ~1 f% c/ J9 @" B! a) I1 }. u" y' R, k" a& ?& e6 x% H% @9 S
if( size > 127 || size == 0) return NULL;1 O( l" M# c+ I% M
- V4 \0 `/ \4 M% Z p1 = SmallMemory;' p) j! T* e' k
while( *p1 != 0x80 ){( @$ |" L* [, T# B! l" ?
len = *p1 & 0x7f;
5 z& N! t f& G. n5 o if( *p1 & 0x80 ){ /* 找到空的内存块 */
) n9 J1 I) V) C2 T9 R: ^' E while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */' @+ b& u% L' M5 @# |- B
p2 = p1+len+1;
' ?; Y, p: _: f" _3 E. ~& v if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 *// F. ~1 v- s8 U8 A" y: t8 m
len += (*p2 & 0x7f) + 1;
/ y1 G/ [( [1 d' E! ^ }else{
! ?& f1 d7 j# |* r4 [ break;# k; D D: g d- e) j ]
}
( q; f3 K6 O+ S0 S+ r }- I1 r* F* ~: g4 S1 r
if( len >= size ){ /* 找到一个足够的内存块 */
) J1 X$ I- @7 k1 F/ c" o4 V if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */1 w6 z4 n4 S+ }# }/ ?- o! h! x
*p1 = size;7 y% @2 N& ?2 G$ Q d
p2 = p1+size+1;9 t. J* V/ S1 n% V
*p2 = (len-size-1) | 0x80;
( P/ l( X8 ^. p1 X$ P1 K, X return p1+1;
" G3 T' }' Y2 W& a }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */( w' g7 i& u( u* L4 |4 z
*p1 = len;( h& ~8 R1 m/ q1 c/ T* k' }, P
return p1+1;# V, k- a! [6 R& y" }4 J2 ^/ e; N
}
' _) q7 X0 ~ i# }7 v }
/ u. V/ V0 G: L2 ^" A0 W' ~ }
- K2 h$ T2 c# }* e p1 += len+1; /* 找下一内存块 */
# A+ G: h' [6 D4 V6 \$ ~8 @: V" F }
; K ]; N% d) e return NULL; /* 没有可用的, 返回 NULL */
- v$ t4 Z: ~( e M; h* ^}
& v# a7 ~# H. E |( J5 l; M! X' X* ^: c* v$ j4 | ?
void small_free(void *mem)
9 v8 b. ]: x0 ^# s; O8 ~{
1 o# T" L6 Q& p3 N *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */$ j6 _! R: `4 l8 l9 Y, J
}, Z+ ]" Y( |9 S+ a" b2 ?
* G+ V# z3 M7 R! ]$ p8 B |
|