|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
* r4 D$ i3 {+ F) Q7 |因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
8 a1 j3 H! H9 ?, {) T正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
, o0 s' R. _% `* g# k
5 Y, B4 Z/ m+ H" G; ]/ O3 [8 \- R9 x! r- Z9 D9 ]+ `& q
仅三个函数:# M3 \ C$ n" {
1 d" ?; N8 [/ I& u9 a% c8 `
<<SmallMem.h>>
+ O: i o. ?+ M* G; s/ O
: A# X+ B1 K) s6 K, t0 P% o, L/ W/ Pvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.$ n& Z7 p; i; f! w) G% k
4 o3 X& `5 x# L/ ~+ Evoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
& T2 E1 S I# y8 w 分配成功则返回地址,否则返回NULL.
0 K8 ^* R- R k' \5 l1 k( U
, e2 v7 T5 ]. |& _" Tvoid small_free(void*mem); 释放内存块.! g( I5 e, \+ B8 t) N; `( ~
& i+ y0 i0 U8 R; @, m
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
: F5 ^0 v9 a6 s+ V5 N<<SmallMmem.c >>' k x4 D, H: _! Y. ^
$ B/ ]% V( a( A E
/***************************************************************************************************
6 U& w0 t% `- R( C( d* W Small Memory Managment ....3 W. b2 G, h, s, `: g( N
Copyright 2008 by David Xie
1 Y' B5 U# m; f7 m4 \
0 X+ `4 ]; Q- c Last Change: 2008-10-10
5 Q4 e& D& t: K$ P/ [* r
$ l% O. z# P" o9 ]/ ?2 t ListHead Byte: Bit7 = 1 Free Block
4 z# ]. x' w6 U; O# F5 ~ Bit7 = 0 Used Block
2 G2 i& y4 q% t: ~9 `
2 o/ T: |9 x1 F* z& @, ]2 u Bit[6..0] = 1 - 127 number of bytes of memory block' Z/ m* w6 q8 X0 a* S
Bit[6..0] = 0 end of memory block
/ N& k# u s* B* d% x2 F9 V******************************************************************************************************/. J2 i/ Z/ w) {) y* k
- [" \2 F! {# L' B% S; R5 w#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
. f. w" P- Z6 v( [) f#define SMALL_MEM __xdata // XRAM
' _$ \, j. |& H9 Z* {% [3 l [. }% j. z, Z
//#define SMALL_MEM_SIZE 256
& i" D( n; `6 l; V: h5 V//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
' M8 N" N/ L$ f+ E! k9 D
/ [; G; R/ Y& K) b* i/ [$ uSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
+ M, e4 k$ i d/ [ T% t/ A6 ? b- y) y3 D
void small_init()* H3 R/ z/ W% l: J& P. _/ J
{# n; Y. j. G/ {& D/ R
unsigned int i, n, len;4 T4 {5 x0 k4 {4 x* @& G
i = 0;
; \1 g: V! D4 U n = SMALL_MEM_SIZE;: B8 O9 w5 ?0 H" G
) U: I( n; q) n+ R if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */, `0 ?/ j: h6 u {% M1 ^, l
SmallMemory[0] = 0x01;! ?# |. f' v0 M) p u* u5 b6 V
i += 2;0 Z) v( H g" O$ P, Q: G: Q$ Y a
n -= 2;
8 m( R8 n9 {5 ]6 x. Q6 x$ ?$ e! O }* i" k3 J* O7 B& G/ s
/ f' d& h! |1 I8 e, c- V
! Z5 O5 C8 s. g0 A( u0 I, k; G while(n>1){ /* Init Empty Small List */: G$ u) x6 Q& ]7 r a9 P
len = (128 < n)? 127 : n-2;
: d' f& J3 M. p3 _) j* t o2 e SmallMemory[ i ] = 0x80 | len;
# H v% O$ u9 G" [' z: a len++;& p2 I& r% z. d8 O# p7 D; P
i += len;9 c% r, _7 f- I8 l* {7 I1 N: w
n -= len;9 S' Q/ ^. K* H% ?2 u
}) ^+ C5 N( |9 @4 ^0 N A
SmallMemory[ i ] = 0x80; /* End Of Small List */
0 j& g/ C7 z" C7 F: g: E+ X ~$ B/ g4 r}
7 D# Q8 p: x. v. c) U0 Q# u2 ^# |% K4 d4 s. P8 c' _
void * small_alloc(unsigned char size)
! X9 c2 Q/ ]+ L n- X& W# ^{
& u$ p* P; W2 ?5 c register SMALL_MEM unsigned char *p1, *p2;$ j; d1 {2 [1 g5 }5 V
register unsigned char len;
3 \3 o* |- {' |( W' r" V: D0 E s+ m6 {5 d
if( size > 127 || size == 0) return NULL;0 z3 {; J/ f/ i n
F8 b/ D1 f7 G! _
p1 = SmallMemory;
* U1 \" ]2 l5 s+ b3 n6 c: v6 G while( *p1 != 0x80 ){
5 P: o( t3 A+ k. c3 z# ^1 Y6 g len = *p1 & 0x7f;
* y0 t- {! Y- p4 Z8 n) _. q. T if( *p1 & 0x80 ){ /* 找到空的内存块 */
1 H. L+ o' @2 B! ?+ z while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
/ y8 `# G1 z8 R+ Z8 B! E( o( H' f p2 = p1+len+1; $ t4 E, o# Y/ r
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
1 t' M X# x# g b& w. ] len += (*p2 & 0x7f) + 1;9 N$ L, R7 T8 b6 L2 S. G2 X
}else{# d# x, {7 a# `4 u1 ^6 j- \) w
break;% A" b7 H) k$ K1 r
}- S" r6 F) f J' {' T& K8 Q
}& z J% m' D3 Q" ~& f
if( len >= size ){ /* 找到一个足够的内存块 */, U! g& N( g0 v' H8 V1 D5 Q
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
+ e' k R8 ]- I/ ^' D* `) U *p1 = size;
b7 H, I1 I& G) A1 T. n; o' g p2 = p1+size+1;
+ }$ [0 r4 O2 l( ?- g *p2 = (len-size-1) | 0x80;0 J+ d) E# F5 Q+ R8 Q1 S3 a
return p1+1; v7 h6 g* a0 }% Y S
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */0 J* J! V- g6 ?' E( y; u: o7 H& r. e
*p1 = len;
8 H6 x' r3 r+ e: F return p1+1;
5 Z8 g7 K% Y4 j- L: [/ \4 U }
3 a9 S6 t" k; r$ {- H }1 J# G3 m. ^0 k1 S. y k' Z& ~
}
) H2 }& L; b- j2 ], c; i1 c( g& K p1 += len+1; /* 找下一内存块 */* X, ~* H" V) p9 B
}( z/ [5 |8 P& H0 g+ l
return NULL; /* 没有可用的, 返回 NULL */
% A* W6 i6 N) K4 `}
( f4 x9 }+ R# e6 W. A2 N- z/ i/ ?) p" B& ]. t2 L) ^$ f* G
void small_free(void *mem)
) Q# \1 w6 Z+ F4 W: G7 O/ X{$ R+ h: V2 ^/ _7 ? K# |
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */9 P" R# Q- x2 H# l j
}' V, m: A; H2 N. f3 G' E8 P7 ^
/ d; B" H u% f3 g* l+ }% v |
|