|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
7 E9 f1 A$ l1 t) x& b因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.( ~9 C! z* K, j! l
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
7 ~+ P" I$ f1 V7 X5 w9 v$ E N2 z6 @' V& w
, Y" C5 k8 E4 I' e
仅三个函数:
% q+ p! ^! W! W+ A2 l1 a" E" n7 D# G' @" o( ^
<<SmallMem.h>>
$ @2 F3 }) I& c! j/ h& v5 M/ ?/ w. M, }. O& b( W% O# d" D
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.) m3 D% l% T" T: E
7 t6 z: u/ t3 e C) kvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.6 j0 J9 x0 x0 N \! d# o% G! g
分配成功则返回地址,否则返回NULL. ( _; C) e) Q, b9 O" M/ p
: T+ c1 ^% f; g7 U6 Uvoid small_free(void*mem); 释放内存块.+ h- [5 c8 u5 p
) U6 j% K9 U: e7 F$ \
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3 k; v* f8 D6 Y& }# q4 ?3 w+ p<<SmallMmem.c >>- L ?/ W4 ?* c/ `) y2 F3 w
7 e. i; m, `1 g$ i3 p( S/***************************************************************************************************/ s0 E7 {9 T0 Q& d: W& m3 H
Small Memory Managment ....- @3 `. N/ w% v
Copyright 2008 by David Xie
& _6 Z' s. D. d7 u
5 L) T3 n5 Z- D0 g. G' p Last Change: 2008-10-10, i6 H7 _# V6 w1 x0 ^+ L
8 X4 _& \3 t' ]/ |8 R0 p
ListHead Byte: Bit7 = 1 Free Block
0 \: Y& s2 h N0 X) { Bit7 = 0 Used Block; n1 d4 D# F& \6 ] K# A8 D
5 _2 X0 b3 f, A9 s
Bit[6..0] = 1 - 127 number of bytes of memory block
, x: I2 y0 f! p( {( u' ? Bit[6..0] = 0 end of memory block' L1 a/ H a6 c S. x0 f) i5 L2 z
******************************************************************************************************/
# w. r- c" y6 ^3 U( y& d/ v
1 n6 R1 \# G) y$ J [2 V#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
. B" ^% p5 e: p C- k/ b#define SMALL_MEM __xdata // XRAM/ g2 T% a- q/ L
/ x. Z4 V9 Q+ D' v" q5 P# I0 z" Y//#define SMALL_MEM_SIZE 256
+ G; f) n* W% C3 K2 P5 z//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
" ^; g! @+ }( j& r4 \
5 r1 F$ W s$ L% V8 Q9 XSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];3 j$ }! L" \1 I3 ~, {8 W$ o2 a6 q
% @$ Z5 l; p! [- `. ], uvoid small_init()
& u( S+ d- ^ E- `, F9 b+ a1 m{
/ T2 Q( c: Q G) K1 O. ?- K7 s unsigned int i, n, len;+ f0 u. x! |( \# B- Q; h# m
i = 0;, r# u, Q8 S4 y# t9 G* K
n = SMALL_MEM_SIZE;
: S6 b! d. v$ [7 J6 J7 |
4 p1 P9 R. a( h* I. ` if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */# H& n0 h7 V( K
SmallMemory[0] = 0x01;0 u3 F2 U f# ^% R4 }
i += 2;
' \+ q/ g2 a2 `/ i- ` h# K: a% |2 M n -= 2;, v! k+ y" j/ c8 R# ^
}: B: i8 n+ C9 {; y; I
' c- ?; y+ [9 k$ @6 h2 u6 M
6 Z# N1 n9 d( T( g while(n>1){ /* Init Empty Small List */% Q' e! f3 c3 U+ E" T6 m
len = (128 < n)? 127 : n-2;) [; l5 i1 ?! C% `) E
SmallMemory[ i ] = 0x80 | len;
6 D. }2 o5 g6 T len++;
1 e4 J5 w9 o' N+ l8 ^9 q# h) W i += len;) H6 E' r8 v0 A" {
n -= len;
* H' F/ Z6 q" E- F }
* j( J9 @( I% o3 ^/ ] c# Z/ F2 V7 F SmallMemory[ i ] = 0x80; /* End Of Small List */
/ f0 c$ z" w3 P+ y1 `( c3 E}7 _5 }2 W8 u2 l9 P4 @5 {0 y8 H l- v
' V4 I& @% r* g% E9 x3 F
void * small_alloc(unsigned char size)* \- O f: q8 M/ M" {
{- ?1 X( R l: ^) ], E
register SMALL_MEM unsigned char *p1, *p2;- P. k8 p: _6 M+ o; x, _
register unsigned char len;
]) _ q2 Z) i j l1 g! [% q# e$ G" q7 A
if( size > 127 || size == 0) return NULL;
+ f' X0 I9 y2 u5 {6 H/ S
; \2 B, h3 ]0 ]2 G/ d& A6 X p1 = SmallMemory;
/ k5 V& a; e- f4 Y3 j# V* _ while( *p1 != 0x80 ){ G( {2 p* q# }& h7 ^, u- `
len = *p1 & 0x7f;
# b% p) ~- Z Y if( *p1 & 0x80 ){ /* 找到空的内存块 */0 q+ ]; {! q) x5 R8 Q+ Y
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */8 g! R, L& d$ e
p2 = p1+len+1;
9 ?% }" b D2 y1 ^2 _; d$ p# q0 n if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
8 }. f0 y4 ^3 }- s* {& e len += (*p2 & 0x7f) + 1;
6 J, j9 E2 S! d7 I; M }else{
6 L' e0 |( ]) T; G break;: L- m, j8 \( V( S6 ~( d; u O- M8 E
}% T# `3 L. M+ c* j/ A
}
# y1 [3 ~( Z* W' F4 `- N if( len >= size ){ /* 找到一个足够的内存块 */
# G2 }! C P' R ~ if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
- `4 s5 y# Q) \4 m# h- | *p1 = size;
% k& m! H, D+ _9 Z, v p2 = p1+size+1;7 Z6 }8 k4 `+ Q% b" a5 [ v
*p2 = (len-size-1) | 0x80;# b) z( P6 ~* i; u
return p1+1;6 R1 b; V$ C6 d- K& t( q* y
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */. C- i/ t7 w; K; H+ ~/ {* Y
*p1 = len;# |$ X8 Z8 e2 M" ^0 l" m$ z: W/ [! R! z
return p1+1;$ E, W+ ]6 \& |; D
}5 n2 ~- S& |4 C+ ?( n
}! I) {) `* d$ v, r% v; S n) a
}
! @8 _0 o" }# f8 Z u p1 += len+1; /* 找下一内存块 */
! L3 l% S) \* T8 M5 z$ m }- f3 }/ G# @8 M$ z
return NULL; /* 没有可用的, 返回 NULL */
* j2 h0 ~8 C5 r' R/ z}
4 J3 L4 o# { O- b* \% y
6 D: p5 `$ I& n$ ~void small_free(void *mem)$ j9 u7 A! l; S- _7 ~
{
7 }- Y0 w, ]! @' | *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */5 ?, U: H8 H; \0 g7 J; T0 u$ @& F' P
}' F3 _: ]$ I- F9 z o. f1 S4 v$ O
% H4 c8 b4 o8 E/ x8 r4 m$ E |
|