|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).; w/ B" D A7 U8 h1 m, n: E
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
& ]4 W; n( Y- ]1 I. A8 T- m正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
7 A- i" A2 k- u1 R8 ]" P/ b. `3 P1 T/ F. e& f) K$ S3 k
, j( k6 _& U- x7 B2 |- x3 ]4 `仅三个函数:
9 M; I( z2 K: ~% r2 `, H8 i5 m4 x
<<SmallMem.h>>) U) H; b7 b' s& [- t
/ V- \8 V S0 ^
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
5 {; l5 K, k5 D# z q) v0 r8 R! Z. |8 p9 m3 [5 ]- c$ h; @
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
( Y8 k: _) A- {, b+ }9 O1 ? 分配成功则返回地址,否则返回NULL.
9 x0 C3 b, K1 V; O5 |7 Z) T o6 b& g" F( u: X& S
void small_free(void*mem); 释放内存块.
4 q6 ^1 y& |6 [
# A& \5 a7 B2 \3 m& b-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4 f0 j4 Z' W5 J$ O<<SmallMmem.c >>0 Q# t; T- f- @; [, X2 D: ~4 L" C
2 C" n2 m8 I' r/ T$ N% t# N, h
/***************************************************************************************************
% ?+ h: E# I5 ]- p6 ~ Small Memory Managment ....
% ^# x7 H' n& E r Copyright 2008 by David Xie 1 ]( h" E& ^3 Z6 D4 ?: e" j; ` E) K
$ C: `9 p: Z& D6 ]! F3 o Last Change: 2008-10-10
7 P* h* c! k }8 n
2 ~( a: v3 y& S9 f b ListHead Byte: Bit7 = 1 Free Block) }' R' S5 b. K: J3 l
Bit7 = 0 Used Block6 ~; V8 ^$ H1 z5 ?2 q$ V
4 B' j, B5 @& r5 ^! S K1 D/ R. s _ Bit[6..0] = 1 - 127 number of bytes of memory block
% T7 T$ @0 J5 y- N B Bit[6..0] = 0 end of memory block# [5 @! G$ _! `
******************************************************************************************************/
# [2 X2 C7 f# E2 M% u& @, ]
$ U! ^) Q; ^6 l& |& H8 y, X5 I' C; n#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
~# b8 g, U+ x#define SMALL_MEM __xdata // XRAM( ~6 r( K4 M) U' V) D+ l
; q _2 m4 P3 a$ P
//#define SMALL_MEM_SIZE 256
^5 m8 i7 e0 R" k1 s//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用." b1 w$ E* g% I+ U- j
! G8 O2 a& S C: I- \
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
& w% p _% X- K9 m) x9 s3 t' }( I f! t
void small_init()
/ r+ V1 M! @7 j4 l( r* l{% w$ c- p+ ]- b. b6 e, X8 Z
unsigned int i, n, len;
$ T$ o. h. Y; u9 I7 z i = 0;# M2 c, Q$ t3 i& I# _
n = SMALL_MEM_SIZE;3 |. I6 U+ H( Z4 X- {
2 H! ?& [1 W: a5 i
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */5 ?; [! }& V+ q4 |2 J/ g
SmallMemory[0] = 0x01;/ ?7 n0 |2 S9 ?( q' K! H% M
i += 2;8 v3 w3 q2 w0 P& Y8 \
n -= 2;
# L v" L; r- e9 }2 k) ~. B/ C, w }
7 F) ~ d7 L) _2 `* w8 b( L/ F6 S4 A2 |
: K; f9 \: t# h9 x( i4 F
while(n>1){ /* Init Empty Small List */
9 }' v6 Q9 p- K0 N len = (128 < n)? 127 : n-2;
- j. i& }% c3 ]6 U2 x, K SmallMemory[ i ] = 0x80 | len;6 M5 r/ X. I( M2 a4 v! [! i* o! |
len++;
" i" E5 ], Z" d9 i i += len;
/ A, X P+ @2 T: N n -= len;7 V/ g8 A6 s4 I8 ^2 y
}0 _3 W- A7 b. E0 a% `
SmallMemory[ i ] = 0x80; /* End Of Small List */
0 w/ X" E# L+ M% v& l% B}
# L) y0 J( Q# P
" n7 Q) j2 i) C4 _6 W+ y' Gvoid * small_alloc(unsigned char size)
& z0 J5 N6 M0 K, o v/ r) B8 ]$ m{& r. _- l- U& Z$ {
register SMALL_MEM unsigned char *p1, *p2;
# ^! ?9 ?) ]7 f+ d1 \5 I' a' l register unsigned char len; W% ~/ _1 L2 `1 X4 Y2 E
+ `7 Z0 I- E" M9 Z* U' A
if( size > 127 || size == 0) return NULL;' R( ^" n! v% @
4 D" c( L3 E G7 W& A" U" g p1 = SmallMemory;
' i+ Q& Y/ Y/ q# g5 o while( *p1 != 0x80 ){
0 t) w/ g5 R* F len = *p1 & 0x7f;
: ]- i8 l+ s7 K/ y- H' I. ? if( *p1 & 0x80 ){ /* 找到空的内存块 */
. w% E. b+ O* D7 m! ] while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
7 t/ h) t9 n% z* c: i$ {0 Z1 i p2 = p1+len+1;
W% R, ~$ x) |7 w/ I0 \1 ~ if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */# G/ W% Q$ M- V$ E) J
len += (*p2 & 0x7f) + 1;& g9 L) t/ L3 T: A: I, R0 S1 l4 t1 ?; \
}else{- @& F# w3 C) c* x9 f7 J
break;7 o- r2 J: N6 G
}
: ~7 @: _9 e5 `$ B4 B }
1 x, u K! q2 u8 u if( len >= size ){ /* 找到一个足够的内存块 */& E: L$ h- C, B8 B/ g
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
2 h% w8 @: I2 c' K, \' x$ O *p1 = size;
6 S. h7 K& }3 S& i+ t p2 = p1+size+1;
( }# ^0 [* }% L, N, f5 E. E *p2 = (len-size-1) | 0x80;
5 y" h, V& _ v8 k l3 r return p1+1;$ A0 \+ D! }/ E7 }0 h8 j4 {
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */+ O% i, t' |- i' K/ C
*p1 = len;6 S" [2 R* v- E( E1 k- z1 ]
return p1+1;: J, ]8 L& w; Y$ J: {. T7 n
}
/ n3 W: }& f9 L- V5 L }' F* |: R, m0 d/ J
}
4 R9 p" u# W9 B" ? p1 += len+1; /* 找下一内存块 */: d: P0 M( ^/ r* M2 j7 k
}
! h& D, B# c' b return NULL; /* 没有可用的, 返回 NULL */
4 k' `; z: Y8 _7 k5 @0 l. W1 X}
# {4 T' n7 G/ N" u+ a0 {
4 a/ i( J" u5 ^/ X9 K5 r% Tvoid small_free(void *mem) u1 T! ]8 D4 N1 f+ D, {- ]
{
" l3 x0 D* a7 x" C6 E: h *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
8 M. G, R+ y+ [- C1 G+ G}
# \7 u2 r8 g) ?0 f& d0 l" i
" r# S/ b, e/ W( [! M! V; k |
|