|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).7 }* m+ C5 f7 A, J2 e0 I
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.0 n- ]8 Y3 D8 }0 H/ }, m
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:! f: e% U' i$ L7 H0 k8 e
8 q/ ~8 T9 |8 O
# c# w2 \+ O( P8 x
仅三个函数:
+ g- O3 m; I! N. m/ `
: K A6 C' o7 c0 Z8 z) o. g<<SmallMem.h>>' g4 m; F& A% W# j# G6 P
& ~$ \+ K$ B7 F1 j; U6 I" k2 w+ gvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
' S5 a8 _, A6 p
d. ?; \. h6 y' Ovoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.* o+ Z7 H) o& I# P% p
分配成功则返回地址,否则返回NULL.
, g# a- Y! f& S' f0 z. o) m( e% j( z8 S/ r# c9 e% g1 P
void small_free(void*mem); 释放内存块.
' p Z2 ~, k; F$ M) o6 W% ~9 o s% v! v8 j' Y
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------' d/ v. M( M! K+ s
<<SmallMmem.c >>9 V/ ?1 Q( r/ l" e% |2 U( }
5 B/ u8 g0 |# ?4 i1 ]+ P) B/***************************************************************************************************! t" D# d# f( c1 ]3 z5 k h2 l0 z
Small Memory Managment ....& v& I7 z% U* \$ U5 X
Copyright 2008 by David Xie ) i2 G7 z! F7 l# k
# L" W- g+ F! `; m Last Change: 2008-10-108 @& Q% N3 ?0 d: Z* o2 k
, [" o* c0 ?- { ListHead Byte: Bit7 = 1 Free Block
# D" {1 B- \. p3 i8 J4 g! K/ p Bit7 = 0 Used Block( a8 j ^6 F; m
9 @0 ~" g5 x, Y Bit[6..0] = 1 - 127 number of bytes of memory block
" |+ d, ?/ g+ v* V; H Bit[6..0] = 0 end of memory block
0 [/ A: n% S' Y7 a0 L" u( u4 X******************************************************************************************************/4 ?) }+ N. u5 u2 D9 h6 I
" y4 H, T; S4 t' i; M/ D1 d; ]#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
: K9 I' l/ p" p- ^6 p#define SMALL_MEM __xdata // XRAM! E0 d6 V. m: T) m
6 @5 d; ` d C' |6 E ?/ e) G//#define SMALL_MEM_SIZE 256
/ Z( @: ~( z5 i+ C//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
* B, f& O0 @9 {: \* L3 a
( G/ ~- [& w; JSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
- X4 ]6 y6 ^' N" }" Q, ?! ^- E& t
. t8 J1 _ g/ p. Mvoid small_init()
! r! e% h& B4 m: J' t7 g' c{) R1 U( l9 s# E! _' E# w: z. H
unsigned int i, n, len;
1 n' q, k3 `' N* R i = 0;
y9 d* S8 X; e9 r n = SMALL_MEM_SIZE;
& \2 b. w1 K) R0 X4 {) N( S4 Z" x; `0 Z8 _% B; D9 b8 X
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
2 [4 C6 |4 @/ h) G* y SmallMemory[0] = 0x01;/ A8 X: S. T/ R) s" }
i += 2;
( O2 H$ z; I) B2 i n -= 2;
9 s: |/ }4 S5 U }
) D2 y: Z# @ t4 k8 m+ r- w% J, I
# [; r) @( o: [ while(n>1){ /* Init Empty Small List */8 p/ k# \/ w6 N0 p
len = (128 < n)? 127 : n-2;
( S. [/ w# f! N d1 f8 [ SmallMemory[ i ] = 0x80 | len;
: i2 O7 _: ]5 W" A; @* ~( B len++;) F7 T ^6 _0 E- k" o
i += len;
* w, m6 l0 ]! R" I1 j n -= len;
$ _' s# u! F2 i5 P$ T9 `# n, w }! W5 W$ G5 }) @+ }
SmallMemory[ i ] = 0x80; /* End Of Small List */
3 o& q8 ] `) `: r/ T3 R}
! R# |1 A3 J- u$ g- d4 W# n* O0 q1 k) c
void * small_alloc(unsigned char size)
; [. R; P G! ~: L{
; y- q+ _5 w3 _* Z register SMALL_MEM unsigned char *p1, *p2;; l& S8 C2 z) F( G
register unsigned char len;, b- B- Q/ b. X# i! ]+ q4 u
, i. T( d% F6 Y4 W. }1 `1 b if( size > 127 || size == 0) return NULL;
Q: X6 |3 {' k) m" B6 t* u
' S2 H; H Y. }% _ ]- b4 S p1 = SmallMemory;- W8 q# j# X. N6 l. E
while( *p1 != 0x80 ){, z# S5 X$ b+ D+ v9 a# E
len = *p1 & 0x7f;
+ F! f: \8 ^1 [6 J: |, b) h if( *p1 & 0x80 ){ /* 找到空的内存块 */6 u$ }* n: l' }( D' k8 n
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */4 z8 p. C% Z" B1 S8 |+ @
p2 = p1+len+1; # c: h2 ?. W2 M* a
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */3 _ l4 r6 [% A9 v" q0 `
len += (*p2 & 0x7f) + 1;' Z$ c$ f$ b0 Y5 z- {4 p
}else{. ?% _5 P0 H$ [. T' t
break;0 V3 q) r2 a4 H9 p0 ^
}# h: ]& u' p8 X) x$ \7 }
}. C5 ?6 d+ G8 V
if( len >= size ){ /* 找到一个足够的内存块 */0 T* }( E: v' B
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */$ p' k6 v+ K/ c9 F* j2 D' e
*p1 = size;
3 r% q5 b6 N( y2 g p2 = p1+size+1;
4 v( r1 D2 d8 C *p2 = (len-size-1) | 0x80;1 G: _5 M$ c+ B" c/ P- T3 \
return p1+1;: |& m v8 A, R9 L4 p+ c
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */; c. J- O4 j, @* G1 ~4 q) I
*p1 = len;
2 ]+ V _6 J. Y5 t$ T3 N" M* E return p1+1;
0 R9 L6 ~# ~% y. o }
0 N. e2 q! _! z$ [ }
0 d' G7 A8 b. W+ e) q0 q ]# W }& I. ]( n' e0 u, n
p1 += len+1; /* 找下一内存块 */% x% h& l1 I/ E& j1 F9 `$ `5 T
}, V, G, ~' }4 @& U" @, t% G
return NULL; /* 没有可用的, 返回 NULL */
/ t0 q7 W& u$ H6 h}
) y6 r$ B( l1 ^4 k: z% C7 k. M5 B
% u8 d) ^5 d+ \& f7 `# H9 q+ vvoid small_free(void *mem)
* t! ^! K+ o2 N; O0 @{4 J( W- J5 O+ f" z z' @/ t; x
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */: J- A5 r5 i6 v$ R" v$ K1 D
}* L. v. K/ T F) k! X% Q
& ?; ?5 _: z6 g& O3 ` |
|