|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了)./ |+ T4 x: i. k: r# `. u
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
. F9 b- u) l, j正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
2 f7 d7 a, z- G+ l; o
& ~" T* H" `+ @3 N4 ?
/ s5 S. C2 ?2 g3 e; n. l9 h6 p: B$ E% j仅三个函数:2 D0 C2 t% r. l7 M" q/ A
5 T( k6 o4 Y3 C. `' |% G
<<SmallMem.h>>8 U% d8 Y$ T0 d- C8 v
, s5 C6 G6 j- }/ n8 e8 y& P, |& ~
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
, J v9 w4 m% U& m( R+ Q" L/ j8 e; a9 h# O
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
1 o' F! g& J) Z# w. ^" l; I 分配成功则返回地址,否则返回NULL.
1 M6 Q# C, M- p3 l" ?" b* u- K3 o6 T" N, F4 n5 {9 g: A d
void small_free(void*mem); 释放内存块.) S+ c0 e' o, {5 g8 X( p; }1 U+ V/ q+ B
* B" d8 m; R9 F' g-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------, t4 H* ?6 \- S; `& M0 i6 s
<<SmallMmem.c >>
- S7 ~3 q8 c( M( T) _$ s
6 q, z& t( n6 z/***************************************************************************************************- P: Y+ V# B% C' u& ^
Small Memory Managment ....# ^5 q& D' ?" d4 @, j
Copyright 2008 by David Xie * r/ R4 ?9 @3 L
' i5 _! X7 A5 Y. A2 w Last Change: 2008-10-10
9 D7 d4 x/ O- j9 G, g$ Q; A- `5 y( O
ListHead Byte: Bit7 = 1 Free Block1 K' e. ^" I! P& o `0 c
Bit7 = 0 Used Block
: d' C" q$ a" @; T
3 H- G& W! p# L* w Bit[6..0] = 1 - 127 number of bytes of memory block
8 v7 k, _* ~7 z9 X) q2 \ Bit[6..0] = 0 end of memory block) X8 ^4 d8 `5 {
******************************************************************************************************/
8 j ^" ?! F" }5 J: z7 w$ A) G4 |
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
' _( @) r( c8 R# P+ ]% G7 M#define SMALL_MEM __xdata // XRAM
. e8 ^/ o; A/ C, W+ F5 V% j5 Z9 }
: J( r; r* A: D3 g//#define SMALL_MEM_SIZE 256
( U- f2 ~ d5 g$ G, b2 N//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.5 U: L: ^' N, P4 d; ?- R0 a
6 i! v* J7 C1 j1 |% @6 T9 `( Q" T
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
7 l7 @; P3 w3 ~$ ?+ J, p+ s/ _' J; J0 u$ y& u; y: Z
void small_init()5 j$ h9 N ~& I
{
" s, W( o3 d$ O T1 D) v unsigned int i, n, len;6 X& e/ Q+ ]% I6 L( C
i = 0;
# m R, |& z/ L2 Z$ V, D& K n = SMALL_MEM_SIZE;
2 h# n+ J: T* c8 \6 d- A' f: l9 \' \
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */) D* e/ Y, `6 d4 b2 V; g
SmallMemory[0] = 0x01;# ^: _- ?. r1 C% y" d, W2 c
i += 2;
/ ?0 [1 `, Z" x n -= 2;- F K& v4 f3 Q+ I9 ~5 s3 E
}
V7 j3 i' W9 _2 a! j; {) v3 w2 c" k- r% e" J( r+ W: ?7 a1 M& G
/ N' f- o4 T1 f* T# ]) s
while(n>1){ /* Init Empty Small List */
: s# w" d+ v4 q6 _* }' |+ z8 ?+ r len = (128 < n)? 127 : n-2;
3 {# G: M! z& O3 ?; ], q6 @0 U- e: ? SmallMemory[ i ] = 0x80 | len;; H8 s5 N. S1 Z% r5 Q. Z1 h" `' L
len++;% ^7 M5 W2 b0 M& e7 ^. j
i += len;
& D9 q& S! R) r* T n -= len;
7 v. j. P- y' \5 t }' a) ^& V- J; [7 D3 N% M: N! W" `, z
SmallMemory[ i ] = 0x80; /* End Of Small List */: q% ]) e: H5 ^0 |* W) |
}8 h. q- F; _3 {
8 }1 I( u; Y6 H, G O9 |void * small_alloc(unsigned char size)
' f$ H( ^0 y1 e' k, _% m/ ?{
6 ]7 L" ]9 i$ Q/ n, V7 ]7 G register SMALL_MEM unsigned char *p1, *p2;+ [4 l: d* `8 p6 e4 x0 ]
register unsigned char len;
5 i1 d% K$ j6 }; D3 L* ]: x, l
( c$ l7 e8 }# i if( size > 127 || size == 0) return NULL;
0 `( Q, a N: o; w7 W( h% e1 A
/ E9 [0 C; ?1 {3 Z ? p1 = SmallMemory;' n5 I" z5 t0 q
while( *p1 != 0x80 ){
4 b a* W! N' F len = *p1 & 0x7f;9 M! N6 U" W! }
if( *p1 & 0x80 ){ /* 找到空的内存块 */ l, V5 \! Z* T! p3 Q6 K; _
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
3 J1 U/ Y) B5 Q6 c" p/ j. v p2 = p1+len+1;
% [' X$ Z7 d0 m7 d# f1 E/ a if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
- g4 k: X& K: h: F len += (*p2 & 0x7f) + 1;
0 ^) F* J: n) ?# \, X4 }2 R }else{) @) }& w" z9 d. v7 v* P4 X3 m) x
break;. z k) p6 ^0 d% d
}" I2 F1 [* \; v' I& K
}
1 K! t* f+ g3 |- ]1 P# C if( len >= size ){ /* 找到一个足够的内存块 */
+ B" f! U! d( W) A8 ]7 {6 C if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */* |9 t0 }" z: Y6 j8 L
*p1 = size;% `5 M4 B5 ?1 j! K) k; Q. W' X1 \
p2 = p1+size+1;$ N3 U) l5 o" d! S ]2 |
*p2 = (len-size-1) | 0x80;
3 k" T" ^2 |* x7 K return p1+1;- n4 J, [5 b1 v ?+ Q0 z; r5 ]" |
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */% L% A' ?2 U$ t0 p. z9 B" t! A
*p1 = len;
4 z" I2 C' N9 U5 X return p1+1;3 i2 x* b% k R1 p
}
' `" [' F j6 K1 y, e }
+ Y+ `8 n, G. j" I; X/ @ }
7 b% r' J- P" E5 j9 B% B p1 += len+1; /* 找下一内存块 */" [; {6 ?. O( ^. \
}) P8 c# k9 l w, I( ^2 `8 Y; T+ i
return NULL; /* 没有可用的, 返回 NULL */; M/ }# _5 S3 q1 G# G
}
% R+ m7 |. M) G+ `* T: h9 w
& }) {6 U# f X- g; C1 U/ N: hvoid small_free(void *mem)* Z6 ~* h7 Q9 R5 f
{
" K+ S* Q! X9 ~0 Q; s* r! n* E *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
* ^4 k; z. K! A}
7 b3 q2 @# M4 a5 E! Z6 ^- j3 |- \3 p
* q' a! ^% Z Y" ]7 i0 R+ o( t% l |
|