|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
( g8 n ^; A1 I9 w- U7 j因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
& B5 p( Q! l- M4 k正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
0 L. {; H2 [- ~- i! C6 h, B* |, q4 {. Y Q9 X3 A1 @! B5 G/ j0 Y
+ S. @5 V4 e) p+ j+ N& B
仅三个函数:
; n' \3 o+ v) J. r* j: b& t& j1 _& o' ^3 }! ~3 v
<<SmallMem.h>>* b* g# b) o2 I5 n6 r7 y
/ H3 y/ t& A2 z7 k2 k+ L
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
1 @2 j3 N8 \) K) b
7 x: l2 s( c# M5 u% Vvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.- g3 u3 X- v' f i _
分配成功则返回地址,否则返回NULL.
+ Y* |1 a6 d; N& M
! D& H: G' P! m% g2 M, D0 Kvoid small_free(void*mem); 释放内存块.+ q8 C! G! D+ @, k4 ?( R
2 _5 F) o: e+ M0 Y9 D) v$ S-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
" S8 K, r s2 Q<<SmallMmem.c >>/ c+ Z4 _$ l( a9 N& b
, A; S/ ^3 W! Y% K* M
/***************************************************************************************************
# x6 s; ?# `3 Y& ]0 R2 e Small Memory Managment .... r" c0 R# Y8 ^8 ]2 U
Copyright 2008 by David Xie ( Z/ `# y d; o
8 w( l$ L5 N J% G! L! P" p0 Y+ ?5 u
Last Change: 2008-10-107 y: D1 X9 B' Z& g/ A: D6 s3 G" R
7 }" v$ u. l1 v$ o; b ListHead Byte: Bit7 = 1 Free Block
2 x8 T+ m( Y* D) H2 F! a4 D( G, O Bit7 = 0 Used Block
/ V1 h* i% o; ?: M- L: O- x3 T2 W
Bit[6..0] = 1 - 127 number of bytes of memory block
: x- K" B+ S/ e9 N) I f Bit[6..0] = 0 end of memory block1 j C/ N7 L% M* W$ E! {
******************************************************************************************************/
5 p. S0 r4 \0 f9 A7 y, m! v7 h& W$ T. u0 y
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
4 _0 e4 p0 R2 k' l; D#define SMALL_MEM __xdata // XRAM
. H, H- O2 ]( v" s6 G2 ~( |) }6 e" h
//#define SMALL_MEM_SIZE 2565 f& A G+ {) g5 C3 q
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
8 L+ C( \; b, n3 V: ?- d5 v$ h
' c* o3 l9 _$ w* e0 m! zSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];8 E- G3 d* v# U0 j' B3 z
7 X* m: W& j% E0 o1 e+ @+ z
void small_init()/ |+ l( K' \1 B; g' s
{
2 S' J* V9 ~! `8 @1 ` unsigned int i, n, len;8 y7 A9 q S4 F6 P; T* Y d
i = 0;0 L9 ~& h: H1 G' N6 ]' o
n = SMALL_MEM_SIZE;
3 i% H! T! c. d( x. h% F3 r- z5 d0 V- z% v/ u+ S* x/ J3 T
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */' [# R1 o. @0 t# L
SmallMemory[0] = 0x01;
O8 }/ h! M' @" `) f i += 2;
; w* o, ~7 O: ?, \, m# l/ }3 U0 @ n -= 2;
M& P- o8 D7 ` }( K6 ^. w1 g0 g+ @: `
) t! k& W# y- |2 W
/ F. d" o: D7 i6 S' b& n' c) |
while(n>1){ /* Init Empty Small List */' t, {6 Z& X( U0 ]$ N
len = (128 < n)? 127 : n-2;1 A1 ]& d9 U1 o+ n: |
SmallMemory[ i ] = 0x80 | len;
! ~, B; Z8 y$ d. N len++;5 f- w8 C! {/ n/ k; y
i += len;" b+ q& e( a" [% d+ Q
n -= len;9 R) ^6 g P* h+ {( L
}) c; ^' r( M7 L8 i8 Z9 Q
SmallMemory[ i ] = 0x80; /* End Of Small List */
3 F6 h) k- H' m. f}
- a7 K0 p6 C* r5 [& n; r: x( i* i3 C- T' O( q5 [; h. v9 f/ [, `
void * small_alloc(unsigned char size)' l, A9 Y+ T& o: H" ]
{7 i! I, K2 k* P" j6 g, s3 u
register SMALL_MEM unsigned char *p1, *p2;2 w" [3 H7 F; d0 i1 ?: m! F1 Z+ F
register unsigned char len;
9 j; M9 g, [! J" p) ?2 C; l7 _4 D* Z2 E. M- s
if( size > 127 || size == 0) return NULL;" U$ `& h/ z# I, z! P+ V: i
: [7 h2 P+ ]7 a* O- [. y7 u
p1 = SmallMemory;
% V, k* o6 s3 b- t1 d while( *p1 != 0x80 ){& T$ h2 y5 d8 F+ n0 {* f
len = *p1 & 0x7f;
% M$ }0 K% [" | if( *p1 & 0x80 ){ /* 找到空的内存块 */
4 S, M% E$ e. y% _) O4 U5 e" [ while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */' u: M& S& G1 a; A# R! w
p2 = p1+len+1;
" O( x! w- \" w" a8 y- A6 _ if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
7 I2 Z u4 _( Q, R& c* c len += (*p2 & 0x7f) + 1;7 L2 w1 J% _; U8 N* M8 M
}else{
, |4 n- `+ i% V break;
8 k G# P' n# T( v }1 A) Y0 r! V5 a/ X6 C& h
}
A. q( g" I- _% o) Z t if( len >= size ){ /* 找到一个足够的内存块 */
$ R; N7 O$ \% d$ w7 I if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */4 V$ H5 Z$ H0 Q# h( [0 A
*p1 = size;
, I% O6 r4 J/ ~) \ p2 = p1+size+1;
8 j7 R/ t' a; V0 p- D *p2 = (len-size-1) | 0x80;
6 ~0 i9 @- e; `+ f return p1+1;
/ q. x' o4 t0 n4 @# l: x( N }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */+ _8 \6 K7 K$ u* n
*p1 = len;
4 J6 D5 _1 t4 y1 ?4 A/ K$ M& D4 {4 F return p1+1;+ t- M8 f, s; S( G+ O" A
}, W$ M# L- U3 k6 E% \
}
$ Q+ o- M$ c+ v6 a" F }
; N z* d* }& d* E p1 += len+1; /* 找下一内存块 */
. W2 b* G6 v8 P, h6 B2 M0 ~3 y+ A( G }
- x# T6 F$ U( G8 ^+ S9 B! z return NULL; /* 没有可用的, 返回 NULL */
2 G0 p) x# |+ }& V8 S}& A& h+ M2 p7 I& n0 N. h% E& T
: F6 P; v8 B6 W/ r0 t- n
void small_free(void *mem)+ U8 `& z2 N; ~, O$ c @
{
5 D" {" E. A9 ~5 m; Q *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */# m! H% n) f7 F/ [# W! F8 N
}
+ R, r* W2 b7 V
" D4 Y7 `4 y5 Q0 e1 y% J |
|