|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
9 H1 M1 n- r. N( i' I因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
; \( x8 R# O7 T正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
. l7 w5 b9 @$ d% M: h- [- V) ?$ U; v O! t+ P ^( ]
X. }! i- p0 U: ?: i9 y仅三个函数:
' k2 t% D; g0 b N, q
0 G( i% [, ]) F/ c3 K, Q" N<<SmallMem.h>>7 o- N1 F- X; N" U) @
) ]& b8 M3 m! y1 e. H- \( z% j/ ]4 Uvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
4 h h1 G! C8 q" a* h+ Q; F/ F: S# c/ G9 v$ x S) }8 _: f- t) Y1 Y
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
: z( H/ Q5 _9 X- n* { 分配成功则返回地址,否则返回NULL. 7 `0 T+ q0 Z/ ?& s- e
2 y: H5 N n% r0 @) [( ^) C# Q; b
void small_free(void*mem); 释放内存块.0 O9 r8 ]/ h2 M0 G$ }
. H9 } r7 S1 c$ h
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------( q* c7 R+ O/ W! y3 u/ n. J
<<SmallMmem.c >>/ q: V. |: l f6 }+ x
$ S. D2 ~/ l. g. q, M
/***************************************************************************************************8 ^0 M& V7 d7 D. C" O ^; i2 }
Small Memory Managment ....6 K( p& a5 v6 @. s
Copyright 2008 by David Xie 4 {8 h! \( F" W
x8 E. q/ `! I
Last Change: 2008-10-10
) V! X% G3 K6 @) l5 l1 S* ^) I5 b3 G6 {! c! \
ListHead Byte: Bit7 = 1 Free Block& `6 q: o" D2 ?* K/ I: n' L/ Y* y
Bit7 = 0 Used Block
" Q- v4 c) T9 A. p, v: [
: f Z: O c, z P Bit[6..0] = 1 - 127 number of bytes of memory block
% ?, k/ H- Y3 ~6 ?* Z Bit[6..0] = 0 end of memory block" u4 H) N! H8 G
******************************************************************************************************/
! O' W1 m" d" Z7 W7 L- d
6 Y4 Q1 u1 f/ s, V( T. C5 y#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
4 n- H: g+ _* x- c4 _#define SMALL_MEM __xdata // XRAM
8 A" Z' x7 V0 C; v; R
+ z, F4 P8 |# G- E. t7 Q$ K//#define SMALL_MEM_SIZE 256
& L7 A, n, \$ w4 A) Q, u//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.) h1 c+ A. Y7 Z% C
( u- U1 [9 z8 `, y, F8 CSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];9 d0 \; i4 p7 ?9 q( P6 ^ M
: L; F$ A* |6 k2 ?/ c# r
void small_init()1 V( X+ z3 u: J4 v, }
{
- f6 L& v" a$ [- P% G; U unsigned int i, n, len;. u! y0 ~3 k2 k* G) v
i = 0;
) P" C! L! ^% M/ i n = SMALL_MEM_SIZE;
# L- \7 f1 \! `6 {+ A
( H6 h. j$ p, T# P, }) F if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
/ w, |" U/ `4 H9 G O% }2 c! W) m SmallMemory[0] = 0x01;
. F9 t% E% U% G% u( d; { i += 2;
" E: u& A5 |( X* B, a2 c# v n -= 2;
( L$ ]$ T4 [1 v/ i& w3 r) A }4 [& v. ~! Y4 X, b7 U
- {* x& u. H! s! D% q# o+ K2 y f# d( B7 e& V
while(n>1){ /* Init Empty Small List */
6 L! J& g" N$ u" W3 I) ~4 T: Y len = (128 < n)? 127 : n-2;
' n9 Q: g/ Q" `0 s SmallMemory[ i ] = 0x80 | len;
( j e- M3 D% R% J: `8 e9 ~ len++;6 ~/ F$ Y- n# L
i += len;- @+ D+ U$ z8 L- L. ]+ e( F; L0 O
n -= len;
! b Q- ?7 i0 M }: k/ w% q2 R1 f) i) |- F( n9 R
SmallMemory[ i ] = 0x80; /* End Of Small List */7 Y8 ]( E7 h+ [
}
. Z3 C2 }" [1 J n* a5 @6 o" V& g& u' c) ]. B
void * small_alloc(unsigned char size)' S9 f, M( W4 f6 ~2 i% h) |; ~6 w
{
% O V7 q$ z( K. g1 y3 p$ U$ e register SMALL_MEM unsigned char *p1, *p2;
& M+ x- h8 a2 x" z" B" o( ` register unsigned char len;
8 N& i* u: t' N( @) }: x
' M+ `/ y7 G! H" N2 S if( size > 127 || size == 0) return NULL;, {# I' q- K' z
$ X6 ?- M$ L8 h9 n2 e2 U
p1 = SmallMemory;
$ U, K" U" e" ^: f) e while( *p1 != 0x80 ){) S/ ~, v1 |0 j0 b
len = *p1 & 0x7f;' t: z9 w2 g& N9 _5 n
if( *p1 & 0x80 ){ /* 找到空的内存块 */# e1 Z6 z) v. `. `
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */3 [% G7 N& z+ F) ~: ^, q) ~
p2 = p1+len+1; 8 g# w& h& ]0 d5 {7 N! z
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */0 S8 ^- c# f- S& ^. S
len += (*p2 & 0x7f) + 1;
: y* [* j' v; H; t% S( R1 v }else{
& W. Z5 M5 D9 E. e0 t break;" B' x0 q' t+ K' W$ F
}- `/ @' v# P+ F; ~6 P
}8 ?7 S- q% M& y$ W- k9 E8 _0 A# v
if( len >= size ){ /* 找到一个足够的内存块 */
, B* l q& @( `9 y* `& e1 h if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
, ?* O8 J2 c5 t$ [3 R0 y *p1 = size;- e& ~1 P; j" D2 F: z( L
p2 = p1+size+1;
% [: y- V* z: D4 t0 \& \! H0 V *p2 = (len-size-1) | 0x80;$ z8 T" V3 R- s
return p1+1;
1 {/ b: j; t4 Z }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */: M' c0 Y+ `4 I1 T5 ?; }, m$ ?" ?
*p1 = len;
1 c& Z% B/ {/ C return p1+1;
% ^7 a6 R6 \9 n6 Q }0 s5 j' p3 @& e! r
}. Q( L$ E: s+ {& s; U/ J6 t
}
- c& F8 _$ Q% a; ~ p1 += len+1; /* 找下一内存块 */
* s/ f$ L7 ]5 j+ C }" c3 o4 e) ~! w5 S' q7 n
return NULL; /* 没有可用的, 返回 NULL */
% ^0 E# Z" b. L}4 W( B3 G( U9 X3 k1 A L
* ^6 W" r' t/ z" O
void small_free(void *mem)
9 N! s# j2 N, e2 V3 j: d5 n( ^/ p d{2 j% @5 G. K( W; |2 y
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
$ l4 E9 u# u. R. k) z7 V}
' e% O/ p, p8 Y+ f5 R% S# {
* y4 v' z$ A* g9 |( C |
|