|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
! u" r* l4 s& _' c9 d( [' z' i因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.5 L. Y* Z- C2 A. f' W
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
# q k/ j4 |3 f" _. i' x1 s. X
1 U( q* y. P( b* C7 J3 T( D
( @9 c0 M2 V+ w; B# k仅三个函数:6 u: F0 k6 O) @3 K
* T& c$ X+ O- N& J% |6 L% P<<SmallMem.h>>
# m. T1 [+ }% e9 S- R9 e/ _, [& |0 k. e
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.; U# P+ e6 E6 ?9 R3 w6 a
' D- k p- o; D% s+ [! _5 Cvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.: p0 Q9 Q" ~2 q0 T
分配成功则返回地址,否则返回NULL. - c$ L& p# b9 @$ h" y& T. T! ~$ Q
8 P. E) a% p( t" B. @" z5 Zvoid small_free(void*mem); 释放内存块.: z; D/ h1 g/ T& y2 f Y
( m& O+ Y Y" _
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------# q) g+ p2 [+ G) v/ Z7 D1 \
<<SmallMmem.c >>; K1 M3 o8 T8 v+ U
, ^, N6 e/ _2 w/***************************************************************************************************$ }; R9 y2 Y( ^
Small Memory Managment ...." i! u) M$ y& H9 F
Copyright 2008 by David Xie 5 b) O2 X: ^- s: K' o( b, I! J& K# ~
/ m3 B; u4 h0 h5 A! b( S Last Change: 2008-10-10
* t& y9 e7 R8 {' V. r& i4 y5 h: ?# t) n# G
ListHead Byte: Bit7 = 1 Free Block
% q) l2 V5 a1 p/ C+ K$ n0 b Bit7 = 0 Used Block1 l; k% t$ N5 W, J! L* I* O
0 B8 i" I3 s, v4 |6 B+ y1 f Bit[6..0] = 1 - 127 number of bytes of memory block
4 Q/ r) C2 k% z6 i- {/ T5 ^/ Y( t Bit[6..0] = 0 end of memory block% b& e" F ^' @9 e' D- E/ Q
******************************************************************************************************/1 C( @1 X* N) u% i/ Q+ p, W
( ?9 W. x9 D8 J! _1 k2 |! ^. d' S- N#define SMALL_MEM_SIZE 1024 // 依你的系统来定.0 U/ L( I5 \1 z: L* A
#define SMALL_MEM __xdata // XRAM
: I7 b" J: u/ w2 \8 O! @: l3 C* k( N
//#define SMALL_MEM_SIZE 2566 \, f4 `0 M; m
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
- R# N/ @& p7 Q2 X, H
6 q; x3 z: @1 l" S5 _' y; y( eSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
" }7 l4 ? N: R1 y4 R/ }, P
$ v* R! A \3 W8 v/ f$ tvoid small_init()# r7 [/ r" K R2 V; K7 K# U7 J
{
. w# d, l6 P! Y W& J7 ~- z unsigned int i, n, len;
* l, B4 Y0 h* z: d+ H) I i = 0;- E- P) ~$ r, J. o! u
n = SMALL_MEM_SIZE;1 x2 B i) V! r
, f- w' j) g2 L- B5 h5 ~5 T
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */' c4 y, p& I7 M( J- E1 D% u7 h
SmallMemory[0] = 0x01;, h# b$ H( h: ~8 Z, @
i += 2;+ s; d5 _$ M5 e; H& k
n -= 2;* T) z2 R1 l8 {: \5 W3 n
}
" J: I) X" j* j0 X& \8 r4 n j) [+ ^; J8 A% B
; C! q7 b. a1 H1 W
while(n>1){ /* Init Empty Small List */; s; A; t# d, b: ?3 w
len = (128 < n)? 127 : n-2;" u6 d$ C* [6 `& n
SmallMemory[ i ] = 0x80 | len;
' U, A, n4 N8 z1 d) B7 w, b& U* f, N len++;
: ~( z6 e! ^7 S0 ]+ G% a i += len;+ @' Y5 c' z/ O0 P5 y7 k. ~
n -= len;1 r. m8 U) U4 y" o5 ]- K
}
$ u3 t6 B' l1 E. ?, W SmallMemory[ i ] = 0x80; /* End Of Small List */
) Y( D, v) o" l% i6 _1 }6 I, u}7 O6 U9 @+ M9 d; Z9 p# c
) S* S% Y; S6 _1 M8 C6 L- S5 ^+ yvoid * small_alloc(unsigned char size) n: m% p" S* e
{; Y3 F- M. R6 B. @
register SMALL_MEM unsigned char *p1, *p2;
: J! k6 L+ J& v- W Y register unsigned char len;
" h6 O# A+ W' P0 c. _# F9 s
/ Q9 U. Q) M- I0 P6 f if( size > 127 || size == 0) return NULL;
' I- [) G( v; g# m; \( K+ ?9 C! ~0 }1 N: G
p1 = SmallMemory;
4 H: q3 E) |4 g& S; G while( *p1 != 0x80 ){
5 W" s* {. ~, ~ len = *p1 & 0x7f;
, ]$ N9 r. v( s3 I& H4 P% b! f9 y4 e if( *p1 & 0x80 ){ /* 找到空的内存块 */1 N7 K8 L' T% W T$ O6 K/ |
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
, K$ w n$ C8 t' ?9 E p2 = p1+len+1;
# x- C7 w, s$ f8 c. } if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */& s, l* Z* a5 m
len += (*p2 & 0x7f) + 1;% ^' t/ \ c2 @( w
}else{" r) A5 N+ b7 W, B
break;
v9 e8 b) w# p1 y7 ^0 t4 C }4 o$ \+ `3 V ]4 b+ t$ J
}
' X( v. x& w/ W8 { if( len >= size ){ /* 找到一个足够的内存块 */) n; ?- q( S# P
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */2 }8 q+ P' s7 B1 [" _
*p1 = size;. e8 w# x# o5 C% y& e3 d0 A8 v
p2 = p1+size+1;
1 \$ C. d) G- { *p2 = (len-size-1) | 0x80;
3 b, ~) H3 p: T" e& J* D3 N! x return p1+1;2 [* U* y3 l2 u
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
& \& Y5 |7 S7 g( l* W. q6 h *p1 = len;
! N8 c% ~7 Z: z) X/ x return p1+1;
$ U2 H3 h6 ]: j& y, r! R3 A }
# T% t# W: w0 e% Y7 @ H, ` }8 [1 F! d1 N# A2 m* T
}/ W2 X7 g! U8 v# P/ r
p1 += len+1; /* 找下一内存块 */
4 c9 C6 I6 k3 N3 Z0 \/ m }
7 j% N- K& v" M return NULL; /* 没有可用的, 返回 NULL */
3 E# _! `! @) d) a" |4 @& Z+ D D}
6 {+ h. Q: u! ~' k# Y7 z& C0 w. x
void small_free(void *mem)
$ t6 w: g0 W. n, I{
7 i" o% b" b9 N- q* | *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
- U' I+ d9 ^7 L" y) I# A. C}' K0 y$ Z7 j/ w0 b9 \6 X" M0 n, w
3 c# R/ h' x( [# n+ w6 [5 f |
|