|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).5 ]2 b# a v. U6 X& T1 ~0 G
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
: |9 g% ?) M4 Q2 o' F% w正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:3 `# S3 ^3 H$ ?! @ o% ]
`( w0 h7 ]( S; F" a
/ r6 _2 d; e9 u7 r" ~* [仅三个函数:+ [% @; H: Q; k& E v
! G5 I$ _% o0 T" R+ @( |. Q8 d3 w<<SmallMem.h>>; Z7 F ]0 Q/ T% Z% _: H) T
( k1 @* ~/ Z9 L7 Z& x0 y
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
/ m4 A/ y; Y5 A; _! K$ V! ^4 Y/ G. ^5 Y7 w
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
* X) x" Q# ~% G9 { 分配成功则返回地址,否则返回NULL. 4 k e4 C+ l& B( Q1 z* w
+ T E. F; d9 Y. x8 ?0 Avoid small_free(void*mem); 释放内存块.! w2 z" l, _ s/ e F9 N
3 G' `% b8 v" @9 t4 g-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
; J6 v& }1 A* m4 k& G! H+ {3 \4 m( j<<SmallMmem.c >>& {8 k$ N0 U0 R% K! Q* j- [
' K% y) V! v+ ]& j/***************************************************************************************************
6 R; h8 x# |% u+ }( i4 t Small Memory Managment ....
% K6 G, o1 `& P6 G Copyright 2008 by David Xie 2 G$ x3 e* d& y1 |
6 N. w" [+ M% t q, v/ V# T Last Change: 2008-10-10
4 _4 |% |6 c6 S' J+ C! \! ^0 `$ A8 y
- H! m2 y$ h, p0 w m+ N ListHead Byte: Bit7 = 1 Free Block
7 t. ] o' {. b# f! ` Bit7 = 0 Used Block* y5 q% j s ^9 `4 f- C/ c6 o" X
- m3 ^: ]" e4 v6 z0 H, O Bit[6..0] = 1 - 127 number of bytes of memory block
, I' z0 j! }. O8 ]9 \ Bit[6..0] = 0 end of memory block+ B* q, S# ~& r% i1 W! w7 y1 T. ]
******************************************************************************************************/
' C) t2 `( s. t. Q0 N |% k+ }
0 S; p1 `& J- z5 c0 _#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
8 c$ u. J6 ^1 l) w; d3 z#define SMALL_MEM __xdata // XRAM- L* P' i* C2 r& h {, A
6 N9 J3 }4 P) D* f& `1 p5 P//#define SMALL_MEM_SIZE 2567 @; F. D& m3 L0 t7 [" A- |
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.0 Q: X# i/ G; F' L# j8 O4 s
) z) y+ @9 g* T; O, J
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];+ l/ X, I- W. W8 y# |- @* ^0 ^; s
/ U% l! _: l# b! F5 wvoid small_init()
" S4 c6 J2 m8 p! }+ U! y3 H5 E{5 L; }' p5 W$ q; f0 Z0 t, ]" k7 b
unsigned int i, n, len;' i* k! _/ ]* f, C
i = 0;
: d# w3 j, i) ?$ L, ] n = SMALL_MEM_SIZE;4 u: T8 |5 ^9 Y/ a6 L; ?- \4 f2 E; {
: E8 O& f* A6 u Q if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */' R, X( ]' F5 x, O
SmallMemory[0] = 0x01;+ f) z0 V; `4 a+ F
i += 2;" R! w: J! T: e: P0 A G% ?2 E
n -= 2;/ V' \. J- y& q- @/ u5 R7 Z7 i; |# A
}6 F- g$ ^7 s, ^( z2 f: L% B- ]
8 ]2 C+ O9 w4 f) I6 }; w4 J9 X ?6 w* A; S! D. v
while(n>1){ /* Init Empty Small List */
& H% b& x! @% s& y/ h4 @0 K; Z len = (128 < n)? 127 : n-2;
" p5 }" O7 r& t; a* ~5 c: o SmallMemory[ i ] = 0x80 | len;/ O2 S2 W" X5 c' M% X! x: D
len++;( Q& h0 T# |6 Z! \0 ~1 q
i += len; Y4 d p5 f9 s& @, c
n -= len;' S* `' o J+ d2 q( v& z
}
7 N+ s9 P- L1 b0 _7 u& W SmallMemory[ i ] = 0x80; /* End Of Small List */# m+ W8 o) R! M5 x3 _: K; g
}2 d( P9 l" ~! j7 Y
' k. ~' e* ]: i
void * small_alloc(unsigned char size)( g8 X q8 m( ]% u: N4 x
{* y' _( |5 B* q3 ^. d, m l
register SMALL_MEM unsigned char *p1, *p2;
6 w0 n; A; W. C$ k' G5 a2 j$ h5 h register unsigned char len;* A8 u, W7 x. O
! Z2 a7 Q5 |( B- Z! ]# s* U: P if( size > 127 || size == 0) return NULL;& |! q4 T/ C$ ]; v) z% }* ~
9 e, c/ o# u5 t p1 = SmallMemory;
. T" d, _" z Z# o8 R* K while( *p1 != 0x80 ){+ o; V1 k3 c3 E0 W% K* [, F# |
len = *p1 & 0x7f;' n4 m" m3 ~: X
if( *p1 & 0x80 ){ /* 找到空的内存块 */; H, p' [! R; x
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */1 S: A; j: o& [! g9 p
p2 = p1+len+1;
6 L- @: O- d: v' p4 } if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
, {" j0 o" c2 ]- u0 i6 S ?$ x- J len += (*p2 & 0x7f) + 1;" M" z5 w0 |* C; T' P
}else{
# P% X. M1 K0 j8 d9 P break;: N' \0 R6 x8 g' T3 i4 G
}( C2 z# X* A5 s- l, j: X8 K& u* e
}5 g* b- `9 O5 V I
if( len >= size ){ /* 找到一个足够的内存块 */# \% u2 U" n. z
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
7 U0 T3 i: O& ?) i! Q *p1 = size;: r# F7 S4 D4 ]; E3 y+ ^( l
p2 = p1+size+1;. M5 |. E# v4 M% v1 M" C4 }" }9 C* y
*p2 = (len-size-1) | 0x80;
2 C: V0 B2 q( m+ t) I- n X. s( D/ g return p1+1;
A/ Q6 ~8 ~: ]6 G5 N }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */9 L# q: \' f' A1 q9 X0 I
*p1 = len;
3 i9 E9 d* u( q: ]$ ~/ ] ] return p1+1;0 s$ r9 B9 d, _
}
8 |1 P; Z4 ]7 i; d+ z9 M9 ` }
/ @: s* v2 T9 Q9 Y7 f" v8 y4 I }
5 x" z! |$ h$ j) p& K p1 += len+1; /* 找下一内存块 */
0 O, t+ i+ J0 O! _( J) r }
- \' v# T3 t+ ?' v2 b7 m5 H- B0 C return NULL; /* 没有可用的, 返回 NULL */2 r% |" G4 X) S+ ~
}
4 D3 l- ~5 V) G1 P) C" Y7 Q8 M E. Z7 _( _0 Q* Z9 @
void small_free(void *mem)
% Y& S: B, c( v/ ]& p{
' J+ N) n J e$ j, [' T$ X: } *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
- D% Z' H* [4 I. F}* P8 w7 [& Y7 S# y
" Y, ]- m( v8 L: m% y. c# p
|
|