|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
8 Y# K6 Q/ q/ h" `4 w, A因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
7 d0 W3 U1 h1 D P9 m2 h8 Q正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
" l5 Q8 s# K- b$ l: G$ \ U1 b* ^: l" p. C3 O
# ~" S* R/ @, \$ _. V0 N, B
仅三个函数:
3 v8 h2 g6 L7 _! |* V+ i: q# T) z2 z U, G/ C: k6 m3 Z9 _
<<SmallMem.h>>
, @$ ^) Q; p. _3 j4 P$ s' v6 b" ]3 N( ~* J7 N, J
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.5 \: t% G+ A' ~% C1 F
$ s; j. {2 y( y/ u( hvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
% F* K( D/ s4 t- `7 _ 分配成功则返回地址,否则返回NULL.
$ | L4 Y+ z8 ]( z( r& M2 }+ {5 _1 Z/ L; g5 O* e0 E
void small_free(void*mem); 释放内存块.
n' b5 M" W2 y( F8 j0 H! q; }3 O/ t# a
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6 T% O* X, r8 W3 L<<SmallMmem.c >># H$ |7 Y# Y. j9 ~) N4 i; a3 v& l
. n* {& o O' F* T/***************************************************************************************************; u1 O4 }8 G X( ]
Small Memory Managment ....
3 j; S) k; e$ I: G4 f5 J$ C( D( ^ Q Copyright 2008 by David Xie ( @7 ^/ v3 A3 h. A- }
$ F2 N- w6 m0 u& I
Last Change: 2008-10-10& [: ~' j# h2 U, m. R; \' A/ q
% D7 Y1 k7 k! c0 @; T& I5 j# T ListHead Byte: Bit7 = 1 Free Block
, k3 @ |) W1 |" J } t2 x Bit7 = 0 Used Block2 N! }* O. k( H0 ]
' h6 u a/ a9 r Bit[6..0] = 1 - 127 number of bytes of memory block4 x, w; y8 Y d: {- L8 x. }# V
Bit[6..0] = 0 end of memory block
, v+ l% }" c% Q2 }******************************************************************************************************/; G. T6 f/ I) i6 C3 u
' }) R( J# N1 w9 V#define SMALL_MEM_SIZE 1024 // 依你的系统来定.8 W9 ~3 |1 q, ^: u7 A3 w
#define SMALL_MEM __xdata // XRAM, k# n9 S K# W7 x8 |3 Y6 k9 t. s
' W4 c# O/ _* L" J( T3 J& ]
//#define SMALL_MEM_SIZE 2567 K8 }( |$ ^$ L% \: }; S0 ]
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
2 R- {& B9 u- r3 f+ }# M* ~$ J4 d) m7 `" y7 o4 z: X! T9 E
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
$ c# `$ X& l' o0 E& Q# H2 K) g
2 c/ S5 R) m5 V% \$ R7 W$ nvoid small_init()- \0 @3 F. c- B7 m; a% a
{ c& r) h7 ?4 i4 @ J e
unsigned int i, n, len;! r( ?! V( X+ @% {. V) M p
i = 0;
: i3 ~" z+ w/ s n = SMALL_MEM_SIZE;
* [ `6 s( @2 B9 o
* q! }. O" E, _" G4 V5 R if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */0 U1 ]' v; r# e) I# R8 |
SmallMemory[0] = 0x01;
( t' @* s6 J# ]* g5 ?/ _6 u i += 2;+ y; \& q* s8 X3 Q
n -= 2;
* O! R' F$ y0 a( H( r2 X }
# T; E _2 I% `; Z/ c+ i0 @2 ~" B. X% Q) L. C4 Y
% S! \2 e0 K4 L' A
while(n>1){ /* Init Empty Small List */, J( z! c* R8 \/ g9 t/ S
len = (128 < n)? 127 : n-2;8 o8 ^0 v/ Y2 H4 o$ I. Q
SmallMemory[ i ] = 0x80 | len;
l( ^# ~! i1 ]9 t' h# L$ { len++;
: ?) Z& z2 J+ s' ^9 f: L; q i += len;' G; Y2 S) ~5 d6 m& I' c* P
n -= len;" E2 M' G: v+ c2 V. Q4 K
}! z/ ^+ l* Z- S7 F& T9 `
SmallMemory[ i ] = 0x80; /* End Of Small List */
1 r$ r# F0 ~9 z' y& x}
! M; I$ D1 l( {( I A8 q: V& ?5 K$ {- ?' L# d! `- \: i2 \2 P8 D
void * small_alloc(unsigned char size), J$ G+ x3 E% Z. V4 t/ l
{
& z# g1 N& p5 D2 Z& x register SMALL_MEM unsigned char *p1, *p2;0 K3 p3 K3 w" C7 o7 d
register unsigned char len;/ j, s$ K0 _2 O, |- E7 E1 y) N6 h
1 p9 _# V0 Q( W" E: m( m if( size > 127 || size == 0) return NULL;
: n/ R# z2 _8 U9 S4 B7 g
, b3 [9 x4 y+ L. F2 u p1 = SmallMemory;( H9 s& i& \( `2 `9 x
while( *p1 != 0x80 ){* L; G- n( j; j( W
len = *p1 & 0x7f;1 i4 y4 }4 Z# Q' R
if( *p1 & 0x80 ){ /* 找到空的内存块 */
+ x7 E) t; l9 C8 E; s; m. p3 I2 j9 u# G9 b while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
, A/ n$ H' |1 F3 ]: ~$ y p2 = p1+len+1; ! B; U5 {7 ~. `' d5 h
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */( `" v. Z ?& l U
len += (*p2 & 0x7f) + 1;
2 `0 L k3 @0 b! V }else{( j% {8 }' ~) t Q
break;0 V) O7 ]9 Q7 \& V8 _! d$ q
}# u& A& }: L) F, O) }! q) Z; X# d
}3 |$ G) {$ E. X( a6 H
if( len >= size ){ /* 找到一个足够的内存块 */
) A s/ f0 `; @+ L) @ if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */0 |8 ^/ c9 ]& y) x5 z# g
*p1 = size;
/ A; c k2 Z; [5 X% v p2 = p1+size+1;
( ?8 K9 O0 r% v C( F+ l *p2 = (len-size-1) | 0x80;
# P Q$ S5 O, \ return p1+1;
7 S! Y0 f; N0 X$ _6 d* } }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
% E' w: @2 r: P- V *p1 = len;
0 v* D6 g+ n9 p4 h return p1+1;
* m, s5 X) a8 S. j }
6 o3 }# w. z# ~) {. K; e, j9 r: a }/ ^, D5 Y# q8 ]$ P0 {
}+ `2 l& {+ B/ s; d9 M2 ~
p1 += len+1; /* 找下一内存块 */8 k1 i/ p" d& [% n4 M8 E# k
}
6 [. G! X1 q0 G- ^0 n return NULL; /* 没有可用的, 返回 NULL */
1 P0 P: c4 s: P; e}
; ]* a" h1 u& a: i% M7 v$ [
, q! g7 H( h1 j8 F, D2 D6 xvoid small_free(void *mem) B7 z) ^5 A9 ~# N% l, ^( ~
{- v. K# Y, D4 t2 h( i
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
2 [/ F& D0 i( }6 w}5 F& z+ V2 ^' T4 h
5 c3 h7 @" H4 [2 B |
|