|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
; D9 I6 }3 b: L4 P. Y+ ]因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
8 \; q7 D2 S1 j2 t5 ]- C6 s6 W正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:+ F7 [: B' }1 b# {1 J- ?
2 f4 c, m1 o. f6 F
3 `# Y- K9 u8 Q; b& B仅三个函数:
' c, F3 x6 j& n0 E- _! }
% g0 _, f2 C* s( u3 t2 Y2 k9 t: U<<SmallMem.h>>1 R E/ r/ y5 X- U( r7 A
5 |0 D f( d( evoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块./ A! F' i+ G: Y4 d* B0 r7 G. ? F
# m r% p+ G& K; B6 s& k; A
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求. }6 E& P2 Q! P( E" }. N9 X! b
分配成功则返回地址,否则返回NULL. : X2 l7 l$ |. ~' t4 e8 L
* h2 U" p* i/ V( u! r
void small_free(void*mem); 释放内存块.
( B# L% ?7 H2 C: t% M! s9 [
$ [8 I/ v: N+ ^( X V-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% B3 G! n: J b3 }' V2 e<<SmallMmem.c >>, B' j3 ^0 _: T) D
, O8 X. h! {3 S8 V3 o( e/***************************************************************************************************
; }% O9 V* Z- q) A. b+ T Small Memory Managment ....
- D5 K3 t. y- t5 \6 B% P Copyright 2008 by David Xie
8 [* ]; M. `7 Q) u& u8 C1 _! Z0 z! Z
Last Change: 2008-10-10% X' q" Q3 O; Y3 f" U
+ P; J; y8 E; t$ v% j4 N ListHead Byte: Bit7 = 1 Free Block
5 ^- W& h5 {. y; K; e Bit7 = 0 Used Block G, O& p- v' m9 n9 M/ p
* b3 i" O& h* r8 g- a
Bit[6..0] = 1 - 127 number of bytes of memory block* z4 G5 B# ^$ M$ |3 t
Bit[6..0] = 0 end of memory block
+ [ a3 {+ t+ m* a7 N******************************************************************************************************/$ E) \8 t8 ^; m8 O" j3 u
) Y" a. p2 Y. _* T, a
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
( }" j' l6 e+ U$ n8 y8 E#define SMALL_MEM __xdata // XRAM/ p3 Y& V% O. S' Y$ [5 S
0 d8 a$ a. P& @) Z1 T; {1 z
//#define SMALL_MEM_SIZE 256
! `/ S$ V# g* Z//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.% w' o( e& f" B! O9 A) w
) r0 |& j, _# n1 ]& G: D
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
. O$ T, C% g, T z2 c6 \% t) `5 }
, | k( N0 O# r' X! Q4 b: _void small_init()5 Z D& \1 y m$ p
{
+ U# z3 H9 @8 ^: f8 s) T unsigned int i, n, len;: i5 m* C# g8 O: l* q, z1 l
i = 0;1 O9 I S; W& R4 T7 r0 w* m
n = SMALL_MEM_SIZE;
7 D w; Q: ?/ M4 f& P3 n6 L7 H! R; G7 D( ?8 b0 M
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */* f6 L/ X5 X$ x3 r6 h6 @' G* E
SmallMemory[0] = 0x01;
, V' Z0 j; c+ s! T* {* V i += 2;3 ?6 D; i1 f9 D
n -= 2;
6 i, m- `( R q; y/ F7 `/ v8 R8 H }6 l* ^0 s. K9 K) d, {
0 {+ e7 {6 A- [* G1 u
$ b8 y8 s/ D' r# L1 ] while(n>1){ /* Init Empty Small List */6 i- F a1 U1 \8 J
len = (128 < n)? 127 : n-2;
& P9 R6 W( [8 `2 p& v; t1 D SmallMemory[ i ] = 0x80 | len;$ a9 k. }2 {3 r. Y5 S+ ~! n) Y
len++;
' ?4 o" _& {1 i3 w9 } i += len;8 e* S; s2 w' Y+ V9 G: O
n -= len;
) \ g: W( c) w( |) C' E3 ? }# O% \' F2 F, I* W8 w/ O1 A( L: Q
SmallMemory[ i ] = 0x80; /* End Of Small List */
9 }: `9 U: A7 J$ z- T% R}: C% \2 h0 K+ P: q0 a& a
1 y1 i9 c; h5 P( V l& S6 Fvoid * small_alloc(unsigned char size)8 G# I. @* o/ U7 m7 N
{6 w3 K' |$ ?1 `+ \; O C
register SMALL_MEM unsigned char *p1, *p2;
4 w* r! S8 S$ w( k# e3 D1 P register unsigned char len;
+ C+ P# g7 o. _5 V1 Y6 j; X
- w8 d/ c# S' ?0 P2 i if( size > 127 || size == 0) return NULL;
* e3 A# }, Z) Y) z E
+ H; z) J2 X( A: D% Y p1 = SmallMemory;% R6 P% ]! P+ D& |
while( *p1 != 0x80 ){9 g+ {2 [: j( E) I3 v# ]' q) b }
len = *p1 & 0x7f;
' a. B+ @" j: [* j6 a if( *p1 & 0x80 ){ /* 找到空的内存块 */
) i5 U0 ^9 q& V, N while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */0 d8 y% q; {+ j0 V# N p
p2 = p1+len+1;
+ |2 Y5 s% y" Z+ J- f7 {' c5 r if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
0 x% E4 W; A# X' n! E3 ~ len += (*p2 & 0x7f) + 1;
$ q8 g8 H# p& t3 K7 \1 E }else{
, j! f% }# ^% K/ d. H- Y" J break;* G8 v* \' d- |0 X6 E
}
" W- l- L6 d( Q# {+ n2 J }
6 \3 _0 |3 t6 h2 w0 N! g if( len >= size ){ /* 找到一个足够的内存块 */+ s# E& Z5 m& j' H _
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
- X, P$ p9 L, d* r! Q. {5 S0 { *p1 = size;# Z0 _& I5 z. z1 C7 K/ L$ F8 |* E
p2 = p1+size+1;
$ ^# i& p& t3 f8 T3 W1 @; [1 g7 Q/ q *p2 = (len-size-1) | 0x80;, U$ J) [) E: m+ ?: {
return p1+1;
2 C' h/ j+ d+ m9 R }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
1 A, \' k, b2 V+ c7 h& q9 i *p1 = len;2 O9 Z. Q* q5 z( [# c
return p1+1;
4 Z0 `; [8 h9 m i: _) Z }/ w2 I: n' R% |& ?5 h
}$ r6 I# Q+ u3 A0 I. E: |
}7 d9 M0 e$ S# {7 c0 ^3 C
p1 += len+1; /* 找下一内存块 */' p# N. m% E, L0 M
}
7 d- O. `; t' y$ X return NULL; /* 没有可用的, 返回 NULL */- V* }& s) Y' }% x/ u
}- V8 z% z! ~1 I7 }# \0 l
# A0 y1 z4 Y! |; h2 m4 Zvoid small_free(void *mem)
& m8 g3 n+ V/ W w' a3 k4 O( n{
7 r5 R$ ?& H& f6 { *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */7 \4 I4 k \" l, R$ T1 }
}( Z }) O+ k9 _7 W0 D1 a4 a
6 e; T$ K/ C+ `- e6 `' B
|
|