|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).0 ~/ H! L& R" W; w S+ @; y
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.1 |; x9 L; g$ d2 S/ [5 P
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
0 l6 y: }) V4 k% r- J! z x; j( n/ f
5 E3 m/ _# R0 {
/ g, z/ N" j5 ]9 o3 D仅三个函数:3 {5 f' K5 u+ v3 Q9 N
5 y# L0 I6 H! F D/ r<<SmallMem.h>>7 N* u6 \+ ?2 [* B( p) \& E4 S
5 [5 Q8 Z: c; ovoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
9 o+ F5 j0 F- {# R
" Y( M$ Z" V: J& Y' k5 V# \void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.5 I- Z+ _" R# n; S* _+ M
分配成功则返回地址,否则返回NULL. 7 v, H2 q) i+ `, V) w' E
# g: k2 S+ r" s+ z4 b( O$ a
void small_free(void*mem); 释放内存块.
1 p& j* o5 w4 c9 N. }9 p5 }6 A2 [: O# @, s5 k V
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------1 h: f+ o @% G, r- `
<<SmallMmem.c >>. z9 J( L( E- w- m
% \& b! N4 \2 [
/***************************************************************************************************0 s$ @; d, j1 g# |1 [( @
Small Memory Managment ....
- X3 m5 p' _( n% r3 R* x; [ Copyright 2008 by David Xie
/ H* E0 s/ i( U3 i
% |6 N, s& C. R9 [# D" q6 B Last Change: 2008-10-10
: l- [0 _: p2 V! k3 r0 T: ~( u2 `: [0 y: L/ h* w# C
ListHead Byte: Bit7 = 1 Free Block0 Q$ |9 b8 |2 @# ?4 M9 i3 I4 C3 X! o
Bit7 = 0 Used Block9 ^8 ^3 J# c* @7 Q+ u
" m# }" W5 [, h1 z' N Bit[6..0] = 1 - 127 number of bytes of memory block$ t# w$ h3 i$ t1 r2 C
Bit[6..0] = 0 end of memory block# L; E0 A$ i3 L+ n: ~7 R( B& q
******************************************************************************************************/
1 n+ ?9 ]- v1 ~' Q. W
+ o% f. z& f* ?! u! @! H% _$ u#define SMALL_MEM_SIZE 1024 // 依你的系统来定.& r7 w& f/ O7 {
#define SMALL_MEM __xdata // XRAM
) C' S. r! Z- e9 y1 S* ?4 q9 j' p0 M
//#define SMALL_MEM_SIZE 2561 } d9 @9 i3 ^/ I
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
I, ]* ~& r9 v
, M7 Z4 r2 ^9 s; a; tSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];, Y) c4 `; k6 e' p; h4 E2 f# w2 O
7 E2 o/ Z, l* v1 }3 k
void small_init()3 j9 ~! Y, p$ E; s/ `
{
/ @9 I, ^& G: |# M0 h unsigned int i, n, len;% G" M& m! Z4 ^; ]+ A) b
i = 0;. {+ [0 W8 g( v! u- s
n = SMALL_MEM_SIZE;
0 `) g8 T7 i" J( V: v0 C" w; F& I3 r7 a7 e$ F
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
( R+ o4 Q. [$ X0 e8 Z SmallMemory[0] = 0x01; O% t) j. S! K5 p
i += 2;/ _8 ^& d/ K& o
n -= 2;# k- q4 I; e0 J. O* R5 k
}
$ |* a( ^2 M/ z1 X# P" f$ A* W+ I) C$ B. }
; x& x( E0 @; h8 g$ l. p( M while(n>1){ /* Init Empty Small List */
3 M5 `0 ?0 m! `- V len = (128 < n)? 127 : n-2;
: u% M% Z8 A( x SmallMemory[ i ] = 0x80 | len;
8 {+ p: l6 d* G% U len++;
2 z6 ~/ u* ?8 F2 w i += len;
2 |5 |% P, z1 g. [1 x6 I n -= len;& M( l; }# `$ o5 G; [2 l, L
}
6 h, v! o9 K" i7 N SmallMemory[ i ] = 0x80; /* End Of Small List */6 D3 _* s8 |, s/ v. j
}
' {; s0 f+ g" }, Z% {
" {2 R( H; R3 i' u( c" ivoid * small_alloc(unsigned char size)' \ S0 w. U! k G$ w6 Q! ]
{: c; f2 C0 A8 O: z6 F- u3 v
register SMALL_MEM unsigned char *p1, *p2;
% A F ]/ ?) D! c' T/ ~ register unsigned char len;
6 r! R" {+ G* }9 h' L; n* ?
) }3 v0 g4 V- K- M9 G if( size > 127 || size == 0) return NULL;
6 |6 b9 J m/ `1 z
8 q0 @% E: C7 W0 _" B- C p1 = SmallMemory;
1 l1 d! C- D9 W4 Z while( *p1 != 0x80 ){5 S8 t" V1 u/ B- v
len = *p1 & 0x7f;# C _* N( X* `7 g& r& q- R4 v
if( *p1 & 0x80 ){ /* 找到空的内存块 */8 v3 G* ^, G& m* b- y
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
' c3 X. [+ z; u p2 = p1+len+1; - r5 N P. [9 J
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
2 d4 u3 J2 n+ B# i% J4 m3 H, o len += (*p2 & 0x7f) + 1;9 V4 g7 c7 p, y- G; ~
}else{
; p; m) f# R8 Z! M- u r' z break;
% u3 s3 N* N8 \8 c. D: m }
) n8 L2 a+ ^ g/ ~+ q }! M( {4 h# Q, w! g8 P
if( len >= size ){ /* 找到一个足够的内存块 */# c2 }1 L, v6 c/ L$ T
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
$ @1 F1 A: a0 o3 [1 M *p1 = size;
8 S2 B. x2 l# U( ~6 D+ ^ p2 = p1+size+1;: T) X+ K+ M z) b; O c' n; {
*p2 = (len-size-1) | 0x80;, P5 V9 w$ k$ H$ r* p7 r
return p1+1;9 c/ N; D |) q: K3 V* F8 X
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
6 b6 S" }4 O) @( p# U2 T' ~8 y @ *p1 = len;, t: j$ w0 a! i# W7 D) o
return p1+1;
3 P$ Z3 W k* `" x M5 J }# m7 e, G+ S1 {9 [
}. o( V& i2 G' Y! h2 X/ C9 I4 E% [- t
}
" X- @* \# A6 P p1 += len+1; /* 找下一内存块 */
1 C; Z( C) _3 ?* E# Z }
% q+ a; W0 \+ | return NULL; /* 没有可用的, 返回 NULL */5 d+ W: l$ P* `& L/ K4 B8 k9 ~
}; o7 C7 }- p- U
" d2 y" @. a! F. Z; S# p" ^
void small_free(void *mem)
! F3 I s& i% K, W3 l# D {% Y, o& m{
7 A+ T2 E7 L0 Q *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
. M0 ?% z0 i3 ~6 D5 L}
, T3 m t/ X' i& j1 I8 |
( `! q" [1 K4 z& G% L6 \' ] |
|