|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).2 V! ]2 z$ G5 X5 m+ t
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
9 ?) D* Q! C& U6 m4 V% Q0 _9 @正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
' X& r1 O! H5 }
7 Q! M" ~; y& r6 _- e3 A9 \5 b+ D8 L) v1 H! y2 _5 v$ I
仅三个函数:
9 Z" g" m* I; P/ O" c* ~ {
% Z$ R% l4 S# r& p+ y<<SmallMem.h>>
" `0 g: \7 @6 F4 g6 ~0 E
" r4 _0 j) ~6 J, b0 \5 H: fvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.4 Q) }+ B0 Z& C& l, s) a/ A" U
2 @: B! ~# z5 t( Uvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.+ v8 V+ X5 {/ R1 m3 i, K
分配成功则返回地址,否则返回NULL.
' v/ k2 p) G7 F# s" B9 h4 K; ? z3 y0 M' L V
void small_free(void*mem); 释放内存块.
8 _ v! X, q$ [2 a7 b
/ f- T; D/ q7 Y-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------$ S) [9 v* U% _% k( _
<<SmallMmem.c >>4 Y D" a x' M; ?& w) d# d
9 t& Z: k0 c6 H/ W1 A6 l3 t2 z
/***************************************************************************************************3 I) t1 `1 L2 O9 Z" K
Small Memory Managment ....* `% A* W. R% y) Q* D
Copyright 2008 by David Xie
' H) k% x7 A7 q; s0 J1 B7 F$ @5 T9 ]: @* k4 x4 u
Last Change: 2008-10-103 U4 j8 Y1 H! i) N1 X5 g9 r$ O- ?0 D
3 T8 i& S5 I, J8 y& \0 g
ListHead Byte: Bit7 = 1 Free Block- G9 J$ ^' N/ ?
Bit7 = 0 Used Block
0 X5 m C% J0 d9 m" ]! _& v
, w+ ?9 ^/ s* F- u$ `( B# u7 P8 L Bit[6..0] = 1 - 127 number of bytes of memory block
2 A$ T3 |4 O' x' F" w2 ] Bit[6..0] = 0 end of memory block9 E4 \# `3 l8 f+ B0 a1 M6 p
******************************************************************************************************/
, Y, Y3 W9 S1 _/ ~1 h/ ^" a! Y5 ?7 p
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.) o# w' v1 q9 U3 n# J
#define SMALL_MEM __xdata // XRAM
# B: u' `% \* {3 U- I5 h: @3 z- o, K& Z6 r: B
//#define SMALL_MEM_SIZE 256
/ a1 _/ v J% z//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.9 S! i$ d$ ?, Z) S
1 h% `/ G9 @) e f) l0 sSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
9 b' K9 [) w# f% l7 d5 u
2 X1 e# r& R# I( avoid small_init()- E9 G( s, ?: D6 k+ r7 J
{
) V: b, Q& r! m5 E( o9 I5 D! m unsigned int i, n, len;. g4 @0 S8 Q9 `! b( k
i = 0;
6 L: d X0 m) z+ f' Y n = SMALL_MEM_SIZE;, ^" e1 V5 e* E0 y" o O: L) g
1 F6 Z c/ a6 Q( G$ ]+ z8 @
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */9 w4 X |* o, n8 s; e# B/ Q0 Y2 X
SmallMemory[0] = 0x01;
/ |# V& f+ f* e2 t/ g$ [0 h i += 2;: W' v% o7 {; x
n -= 2;
( Y4 x h) B. i% `6 F }
) D: J0 b* @* q" ?2 l1 X% A4 {$ M7 P3 d: g5 t# z
! b8 H* H( `% H+ V2 l* Y1 I while(n>1){ /* Init Empty Small List */
5 x1 Y9 ^$ R) F8 _" s \5 C5 F5 R len = (128 < n)? 127 : n-2;8 M& k& L7 H: i* [9 f" V
SmallMemory[ i ] = 0x80 | len;9 H/ v6 s( B+ y J
len++;
3 r0 q6 W1 [6 |% n4 f i += len;9 I0 y/ d, V9 L, ^6 W
n -= len;
* z6 [( q, v! D; r }
" t3 @/ i2 u5 g ~" x: c( _ SmallMemory[ i ] = 0x80; /* End Of Small List */$ m- M7 z1 R1 B+ \
}
' D3 D9 w) q3 W3 F: S6 v# Z0 M1 M
% M6 B' @0 p! z; s# bvoid * small_alloc(unsigned char size)
; I- Z8 ~+ ?+ n; P% q{# a$ r6 b5 H% `- K
register SMALL_MEM unsigned char *p1, *p2;) s+ A) B( h0 L$ B
register unsigned char len;
4 s8 A! r o2 U7 s; M* Y, j7 b+ R% h9 k
if( size > 127 || size == 0) return NULL;- r4 N: e) p# t, T/ x
3 z s3 M' O- v* {: Z6 F
p1 = SmallMemory;
6 a" Y+ m4 x! {) q& m0 n% N while( *p1 != 0x80 ){
) i( |- k' b* N2 k- v* E5 u# l len = *p1 & 0x7f;
9 p' ]2 M7 C5 D if( *p1 & 0x80 ){ /* 找到空的内存块 */& d. I# o. V# L9 D) E
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */+ A' c' s& Y. P- q1 w/ J6 h' `4 R
p2 = p1+len+1; : a$ u+ i3 v$ Y6 `4 [
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */# h. q3 w8 l1 ^8 p9 d( t
len += (*p2 & 0x7f) + 1;
9 @6 O) T3 w; @! X. P6 a }else{
$ _: Q) L, b1 Z+ V, A# F; A: ]) M" V) s break;% O$ H4 K/ F$ r! U* v
}
& S- a+ v" `* H; D }
+ G+ Y* `$ _) a% s3 U5 G0 C; X" c# v if( len >= size ){ /* 找到一个足够的内存块 */
' c/ i8 L1 _$ G y v5 o* G if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */' S g$ O! L) b6 o. }
*p1 = size;. w0 Y# b. S& H; e5 l; E) C
p2 = p1+size+1;
. c* B, {% f6 C3 H- n0 b *p2 = (len-size-1) | 0x80;
% _: t+ h6 }: f5 z$ x1 u Y return p1+1;6 C3 S" L |1 c8 W* l3 ?
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */7 R$ |# O- j' H5 r
*p1 = len;
, c) N! L& H% W3 C5 u+ t6 p [0 Y return p1+1;
m. F. C1 h7 z2 ]9 s" V }
4 _2 ?$ D" @2 ]/ o Y }
, n; m' ~% q6 }6 y( [' f }) H* L4 o/ h, Y% n
p1 += len+1; /* 找下一内存块 */, N& u0 ^/ l I% N
}' @0 ^1 q { v' u: J# Z: u
return NULL; /* 没有可用的, 返回 NULL */
# P8 y# {: c9 g9 v}
5 h* |% L! U& A( f5 ~0 U' Y* `( W* X' ~0 s
void small_free(void *mem)
^7 U) T$ X* b# o{
$ l: i! F. Z4 L *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
( _+ j& y4 Y3 p4 r- p1 f+ ~$ _}- |6 [6 W4 B5 O; {1 U' o
4 d9 t2 w: D/ I9 P2 a |
|