|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
& a5 k5 z J. O$ R: ~$ P& J: L y1 z9 w因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
1 y, @0 z3 S8 o5 M正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
+ j( _: n0 Q5 s6 U: q* V8 L/ v/ t! C) h9 K6 ?4 E ]* T
; l5 k7 @" N) o+ l& a# G仅三个函数:
3 p+ W' k* ]/ q/ m! t
0 C3 T* }. u4 w0 }- A! i( H0 `<<SmallMem.h>>$ V) a3 r0 B5 K, |% v% \
/ v' r; r7 A& V* q6 n8 h. e8 Xvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.' [" v9 y6 o5 J; i: l
- A7 Y! X. `% j8 u; A( G
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.0 F8 ` ]3 G( E, Q
分配成功则返回地址,否则返回NULL. - M6 Y% _+ Q, M8 \/ ]4 ?6 l2 v( ?
9 X: k* D7 X/ N% `. p. l/ s% f# o
void small_free(void*mem); 释放内存块.% E7 X* E* ~* l4 |8 S6 d
- ~! W8 B' T$ F( `- e7 `
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ f, o. e+ {5 x h5 V3 k<<SmallMmem.c >>1 u" L7 r8 e+ a4 l' O# t" b
2 e$ B* Q: v0 s' f
/***************************************************************************************************0 Q: P, ?( o* \; o8 G5 H
Small Memory Managment ....* X2 L. }5 a3 P; y# G! p
Copyright 2008 by David Xie
+ u) t$ B! s: G, c% K, H
" l9 o$ [! g& e4 {( s& C Last Change: 2008-10-104 w4 ~2 B: w" w8 H; Q" {* L
& w; x( E5 e1 i6 P
ListHead Byte: Bit7 = 1 Free Block
+ K# O }% e! C7 [5 e- ]2 O Bit7 = 0 Used Block
4 s1 S- X1 @ F2 p
% a5 |+ b+ p) y6 N5 H( _3 O$ u$ j Bit[6..0] = 1 - 127 number of bytes of memory block
d( B, O: `# p0 P Bit[6..0] = 0 end of memory block
' a5 H5 \& O, ]. x# ^5 Y******************************************************************************************************/
7 t' u1 U' U7 s
8 E' C8 N' ?6 z' c$ C- R2 k#define SMALL_MEM_SIZE 1024 // 依你的系统来定., R. E5 O/ _- J# P$ K8 \/ i l. {
#define SMALL_MEM __xdata // XRAM
# [( l( D7 C/ c$ m2 k/ H3 X# I% c- T, e0 G% j; Z% g
//#define SMALL_MEM_SIZE 2567 I' |: t. S9 T1 v2 [
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
* v4 O' W! \* `! V" E1 W
# f: V* F' g. i: }8 d) HSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
+ a4 p0 b9 ]" E# L/ y/ g
4 F+ ]5 u& l3 S6 ?1 svoid small_init()4 h& t0 `$ R0 T! n- A* y
{
4 ^7 i" f, w* `/ `$ f unsigned int i, n, len;
! w) p! T4 `; y) p# Z i = 0;5 O/ a$ P# h8 L: s |" o4 s' e
n = SMALL_MEM_SIZE;1 g- n: Z: m6 a1 g, `1 T
_& @! ]/ r6 x: B if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */# i' x& E0 f7 M5 {) }
SmallMemory[0] = 0x01;3 h' W; L4 q2 [ n* I6 M7 N
i += 2;
( T0 V! f/ D* M* q. K# X n -= 2;& S7 j9 a3 O4 x
}
4 u7 k% f+ U3 b' a3 ?7 r- J) p6 v
# ^6 l7 m- c2 A4 G' z4 K% d& C# J& f& Z2 n( N2 v7 [7 [
while(n>1){ /* Init Empty Small List */
% h& x/ ]% U, U$ V4 _! R len = (128 < n)? 127 : n-2;
0 A+ ^" U2 Y# y6 _ SmallMemory[ i ] = 0x80 | len;
: V3 Y7 x& p ^' o2 a len++;' k9 k7 O( j! m) U% ?* I
i += len;
; ]8 Z/ k1 `2 q+ ?! F# |. ^ n -= len;8 I$ k5 _8 f+ o2 x3 T& b
}
2 z7 {% P5 N Z SmallMemory[ i ] = 0x80; /* End Of Small List *// o" c0 L: T. K& ^$ Z# v q
}' n1 b# L: E% O* A9 z
. R& Q% d8 h) t a4 y' N% M, n, \& H
void * small_alloc(unsigned char size)
( W& y- ^0 Q Z4 ^4 ^/ _# c{2 Y. R8 w. p# U' D* D0 ?# D7 l
register SMALL_MEM unsigned char *p1, *p2;
( t0 X) i+ l- y) C register unsigned char len;
) h$ i, `) s" X' M8 w4 k! j3 ^1 f5 e4 a9 s6 s$ C
if( size > 127 || size == 0) return NULL;' V+ b" Y# x# @9 P/ s
6 D6 ~( ~) N8 G; [6 u, N; u p1 = SmallMemory;: J4 I2 `+ {! u" I$ m* B% [8 [% d0 Q
while( *p1 != 0x80 ){. E: \2 \) D$ e3 u
len = *p1 & 0x7f;
, q/ L! x! ` c" D4 [- N$ \) Q8 d- k9 K if( *p1 & 0x80 ){ /* 找到空的内存块 */6 L! D, Z/ H$ ]
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */2 N' n/ w/ |4 V0 A
p2 = p1+len+1;
7 [! v# J$ G, L3 g if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */' Z3 R$ f. X" e: `
len += (*p2 & 0x7f) + 1;
9 X- ^0 V u7 j! m }else{+ W0 @) s b# e
break;# q1 J" u# b1 n' ~
}( |9 M P* T: }- ^( U) q/ i
}4 j0 `2 C8 e# Z G. \$ w. d4 j
if( len >= size ){ /* 找到一个足够的内存块 */
6 J3 g7 A# E- r2 g) u6 V if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */% N0 p! Z- Z; v
*p1 = size;
1 V A. `! r' Q p2 = p1+size+1;
# K9 Z4 O6 Q7 w5 { *p2 = (len-size-1) | 0x80;
6 e- Q- x$ ^4 ~& K return p1+1;* W) F: @% f" _ ^0 u' s- S
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */2 ]; [! {5 ^+ {! m1 o# a
*p1 = len;0 X& H X0 A l I3 D) N2 n2 t
return p1+1;
% G, _' c$ W! S/ S3 S }
7 L7 x/ D' k% q! g% h. S }
6 d4 ]% M' P3 {3 G/ l! g }* l V1 V8 b: C) E8 I0 m# v
p1 += len+1; /* 找下一内存块 */
* K. L) h$ I3 f6 F' i }- G- D5 x3 R3 `; ^
return NULL; /* 没有可用的, 返回 NULL */
; A* u# s+ `/ d8 w}; d4 g2 g' s# \: b( F8 C; ]# c( D
9 U9 C( \% N) a# Z3 ]
void small_free(void *mem)
2 ?* e; a1 r( C; X9 ]# L{
2 H j: _% P/ L! g4 k *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */- [. B& c, v6 @0 T! K |9 D% H. n
}* w7 [ x, v$ e" S
/ ]4 ?% E9 S) I: Z! |# ~. V2 \3 o |
|