|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
, m9 ?. H1 _& i7 G- {% k5 n# F3 R* a因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
- t/ B9 M( T; C: c0 Z' R1 \正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:0 m( T2 @- \2 t; T; {8 u
- K7 R0 ]6 @* A
; K5 l: ~" m4 ?% g* S
仅三个函数:* ^2 G5 W {& U, @, {' o
2 R# l5 C% O+ @" ]4 p
<<SmallMem.h>>
2 _- B0 l: W/ W- u7 S- O8 ~/ v6 L9 _, E3 q
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
* m# t+ I) `% l, h4 g, `9 C4 D
3 A# ?8 _) Q: T1 Rvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
+ n9 S5 P( ^( ~# F 分配成功则返回地址,否则返回NULL. - {& n, T4 b" O
9 @$ Y+ t8 ~+ _1 ?6 C2 Y" _" \* Kvoid small_free(void*mem); 释放内存块.
+ f) G- ]4 b/ j) @& e' d5 s" F6 U& f; b- l1 g" o2 k
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
) @- w( j: M1 r<<SmallMmem.c >>" |7 l. N0 L$ H4 d9 |) @
+ V1 Q: a. [$ ~7 q+ D |) p6 D
/***************************************************************************************************- Q- p' ]# Q2 Q1 s; v
Small Memory Managment ....
3 w; A) j* [- H: ` Copyright 2008 by David Xie
# A9 b" O/ a; }( c8 g! Z' T4 D1 _4 u8 D
Last Change: 2008-10-105 E4 C; x: x. {# |" w+ _
& G# n( ^' A+ A1 P
ListHead Byte: Bit7 = 1 Free Block6 {! p+ D. \3 \: Y+ h; H& |' q8 a
Bit7 = 0 Used Block
% f/ u$ G$ |/ }6 f/ t+ J( {" C1 j/ |
Bit[6..0] = 1 - 127 number of bytes of memory block
/ Q1 F q4 J0 w. D) ] Bit[6..0] = 0 end of memory block* h2 I3 V1 r: t, P! [, y2 I
******************************************************************************************************/
+ s5 W; r/ o/ g( V. I- ^- w2 Z7 S: Q& l" s
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
; r8 w0 g4 Y! F: c: G/ q#define SMALL_MEM __xdata // XRAM
# F, i( c0 @. X8 k2 i3 B7 e& e* g, i5 n, y7 G9 V1 b8 g$ A9 ?
//#define SMALL_MEM_SIZE 256
9 t! V0 M( Z1 v0 Z, y/ i* l//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.0 A3 k0 W" I r
# g4 J4 z1 z& a/ ^
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
: L' k% l" P/ \3 [# z) h
" J' I0 y2 y9 f3 @) U% T( @9 J" ^- {void small_init()
8 i1 T3 s7 c1 P. O2 }' ~( _+ x{
* u! ?: m# h D$ p8 a) ] unsigned int i, n, len;
5 P N& l( c& N7 L7 p' H! m0 B- h i = 0;
; _/ `; B ]2 _+ H8 u n = SMALL_MEM_SIZE;/ ^5 U- f! d# i, L2 J3 U- I* c
" k: }- ~; W+ F
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
0 p: U: S1 U' K9 Q* G, b7 @ SmallMemory[0] = 0x01;5 _4 F7 G& t. c9 ]+ w
i += 2; b: l( B) r6 @7 @* y: O
n -= 2;* Z6 ^9 K5 M5 z* |% C* M
}( D1 ^5 J1 m6 ?' X* E
# h, w% V( q3 e ^' ]
$ D9 f9 R. W ^5 E* l: i+ V
while(n>1){ /* Init Empty Small List */: V/ N! O) P4 J
len = (128 < n)? 127 : n-2;
4 Z" L0 r4 _% N5 p2 ~ SmallMemory[ i ] = 0x80 | len;
0 Y! r& y" p/ j z) b F len++;- s: Y4 ]* y9 b0 X9 }; k w) e
i += len;
: X. p6 D* d1 T$ Z* f- j" ?6 _ n -= len;
# i9 g9 s9 i4 o/ i: m0 W' ] }
# |' ?5 A! `" |( m; g7 b SmallMemory[ i ] = 0x80; /* End Of Small List */9 S6 i8 ^, ^' [4 @
}
1 k1 O- K% e \$ x# h8 k# a7 L1 Z3 ?# p1 i+ l# Z! D6 Y
void * small_alloc(unsigned char size)
. u8 o- ~# ~& r8 S/ }+ C{4 C# Z0 p$ _7 W" K
register SMALL_MEM unsigned char *p1, *p2;
, ~+ }; c- C4 m; B register unsigned char len;7 e7 Z4 w! G' H; M9 g
9 h6 G( H) s4 S1 S
if( size > 127 || size == 0) return NULL;9 ]; B( Y2 N1 O3 b9 R
% L' m9 ~; \+ k
p1 = SmallMemory;- L/ m) r6 ?6 |5 N9 U) J
while( *p1 != 0x80 ){
4 ~' O `# T* r% Y len = *p1 & 0x7f;
! ]' f7 f* D8 b% I, |1 K9 j/ j, Y if( *p1 & 0x80 ){ /* 找到空的内存块 */
. Q) T+ K) u/ F1 L4 G9 y- P while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
, j" u% v) w; t9 L) D2 p p2 = p1+len+1;
3 m) U3 ^( j8 U if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
7 h [ E4 R7 G& ?/ W/ V len += (*p2 & 0x7f) + 1;6 ~- ^0 G' h3 v# d/ @ l4 _" Q
}else{; y( z. G& ~9 R4 y
break;
. n1 Z) f9 @4 ?( g8 [0 d' |. M }! `5 L0 ^2 V) N ]5 @1 V8 w
}! H( U0 n; R* E) @2 D: t
if( len >= size ){ /* 找到一个足够的内存块 */" b6 [) [8 X7 q4 V6 w" [
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */" c7 a; Z E% `& R
*p1 = size;
7 y) X0 F( T/ S p2 = p1+size+1;( p+ x, H) F+ a) c
*p2 = (len-size-1) | 0x80;4 j) ~0 e' S+ o: T& q
return p1+1;
, ^7 e: h d& W+ i5 c# q }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */8 p1 B' g) N% P5 J- t% K/ G
*p1 = len;) g" l" t) @- U7 G
return p1+1;
9 @* z3 v6 A0 G5 i2 v }
; k' I0 |# R3 M" A3 S/ B1 b }1 J* _! |/ i' v* V6 L' m9 n8 C
}
) E% h J6 T) i# r& Z# d# ~ | p1 += len+1; /* 找下一内存块 */" A2 C- T; @7 L( A- v3 A9 o1 ~
}
: O S* b9 W: Z# q g' S9 J return NULL; /* 没有可用的, 返回 NULL */8 d, O% n) }7 C( j( [ M$ a E
}
% o2 R* S+ `5 V) Q3 ]: ]
! j Y! @5 V" M# o7 m5 H, c9 A0 Jvoid small_free(void *mem)
- ^; N( U- e+ l3 m{
/ I5 w" o1 q/ |- p5 S: P5 D *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
- X! R% V+ A4 E6 @: r# F( D/ V}) T+ {# d4 X/ p* t) w: f( m. m) R
* t0 w C4 f5 w9 l0 M& O+ f* v
|
|