|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
! V! g9 k* N0 Y5 E因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.; V5 A+ M% L8 W, L0 S0 r) [
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:) @; y4 Q# Q4 J! b* ~5 d( I- H' H
! x& l' T) d; d; Z* ?
- C: u& N8 P2 u5 s) w仅三个函数:6 e) T$ u2 W2 Y
* U% X3 V2 m( U7 e<<SmallMem.h>>6 p0 m# d; w5 m o6 q# Z( l
: u2 ]$ _0 ~$ V7 p: ivoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
) [( S$ s% ~6 F B
- S! X! j3 [1 V4 _; W3 j& _void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
2 x. ]& [2 X- o3 c$ P! m 分配成功则返回地址,否则返回NULL.
% u/ U3 y: m' R0 b
# A2 p* q$ E: g# H& g- C4 gvoid small_free(void*mem); 释放内存块.
5 @5 }7 l; C5 S1 c* L5 x" v$ z7 H4 K) g
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------1 ^7 a3 _8 Q b1 e: M
<<SmallMmem.c >>
$ W5 y ^: P1 e7 t- T3 I. S" l2 g+ Q6 J, Y- o1 `
/***************************************************************************************************
3 N$ ~5 k5 X( _ x9 q: h0 }4 m Small Memory Managment ....
2 H) d* q& c {; W& f; J( P Copyright 2008 by David Xie
3 W# W3 P. }2 j3 H. U3 Q$ r! S" B( ?
Last Change: 2008-10-103 e7 M. r, R( s, b
! Z$ Q D7 _8 ^- S; d4 u% U0 o* ~/ _
ListHead Byte: Bit7 = 1 Free Block
) T7 g1 t% `& k! I* F Bit7 = 0 Used Block& X4 y* M' ~% t/ m* Y
' ^; X) c0 |4 ]( J
Bit[6..0] = 1 - 127 number of bytes of memory block
8 `8 @; \* d/ S! D; O Bit[6..0] = 0 end of memory block$ d+ e6 n9 b9 @6 c* ~4 M F
******************************************************************************************************/. c) a' a$ q$ m3 p9 G K
: x& k% H2 ~1 m# J# z" }' i! z5 `6 v
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.* M9 T* _# f) i& T
#define SMALL_MEM __xdata // XRAM; N ?6 T D" Z' a
0 @7 B% {4 v9 u0 t# V3 }5 ^$ n//#define SMALL_MEM_SIZE 256! E( Z- o5 D4 R% ~
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.% n1 s4 c& O3 e
4 V5 O$ h! @, U7 C q- L- MSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
+ a% c$ g6 ?$ o4 e7 u+ Y9 Z6 j6 R- ]9 p2 E8 h6 d8 u$ [1 C' }
void small_init()
1 P8 Q4 u7 A/ W4 Y. f1 u6 U. @0 I: y{
/ b& q" D! R0 Z5 h N' @ unsigned int i, n, len;
$ N6 T% g1 `! h$ }. {* r2 A+ }6 g i = 0;
* _0 z$ S* ?+ K& b n = SMALL_MEM_SIZE;9 M" ^4 i9 d$ z, q; G
2 O& W% o9 r# T8 G: C; N+ E3 W
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
7 }5 E- b( B# F r% u SmallMemory[0] = 0x01;) c/ P; ?* J0 W6 e( R6 Z
i += 2;# t% W% }* q' U, y, ]7 ?" ]! J
n -= 2;
: |; S/ d* P. k }
4 R) v/ a7 O- J2 l3 \
- U6 P% J$ m1 L- d6 j. t p1 |0 ^* C/ W
while(n>1){ /* Init Empty Small List */8 [: ]- U, {( J' i- Y D
len = (128 < n)? 127 : n-2;+ l$ X" A2 s% t& R
SmallMemory[ i ] = 0x80 | len;# [1 j: h) ^5 M6 ~
len++;
+ k/ d. U! z# u6 x i += len;
. {, \5 y ~9 h& Z n -= len;5 E- b9 p* u: w& \# T& ^; z. c- K
}9 u/ _' }0 l, a4 u
SmallMemory[ i ] = 0x80; /* End Of Small List */: w C) x8 x) t# _& @0 u
}, m$ X2 k$ N, r+ z' l" `
, G; r* n G+ Y% C8 F$ G
void * small_alloc(unsigned char size)
5 I, n1 }$ h8 v6 y* d: F/ ~9 H{5 e; x& m5 V' R5 h% O9 O, M
register SMALL_MEM unsigned char *p1, *p2;) a. Z$ a1 L( i3 r4 A
register unsigned char len;
, g! C' s/ r3 I2 ^0 D4 r5 d
4 F; I5 j6 s$ K& ^% L W0 v if( size > 127 || size == 0) return NULL;
) l6 S3 h6 j9 J& a/ [! l( o" |: Y. }! [$ C: w" n' k' p; \! m
p1 = SmallMemory;2 {! b- [: e' Z4 E; X$ Q5 f- X
while( *p1 != 0x80 ){* b" C" ^5 G* J/ a7 |! ]/ c; p
len = *p1 & 0x7f;
! [. z% ^6 I, U% t2 G if( *p1 & 0x80 ){ /* 找到空的内存块 */
* i6 B( a/ a0 j, S while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */9 i# |6 g& U- `! M' q+ K
p2 = p1+len+1; 8 c8 j! d( W {9 o2 E
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
0 J' `, h& [3 a9 y8 K0 ^* T len += (*p2 & 0x7f) + 1;
2 E+ W/ \* D1 e$ q7 V( i2 E }else{* V7 }" N& V7 x9 D! s
break;
% X3 ~( U* w# e3 R% F l }( a" q5 {6 x+ ^; i
}
/ g$ z$ C' L# I; J- d' _ if( len >= size ){ /* 找到一个足够的内存块 */
/ A* V, M& M: t9 O0 {: w9 ~ if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */$ ^1 t5 ?9 T+ Q7 v" N" ]
*p1 = size;
5 }8 R% Z1 g- e6 M% x4 i& i p2 = p1+size+1;
- [3 R7 `( r$ x& t" o' ` *p2 = (len-size-1) | 0x80;
% {; b) Q% M2 G" R3 S return p1+1;6 C) l5 V- V( x
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */& g& ?- N3 J8 K6 z
*p1 = len;4 B8 H1 e9 `3 l1 @# J
return p1+1;
7 J! `0 {" s4 ~& W! H }
- P+ |- J4 V* k% o8 g8 z }( V: i1 @0 q" @- ~* n" Y0 k" i+ _* I: H
}
" i0 T6 P8 [+ X3 O3 M p1 += len+1; /* 找下一内存块 */. N, }+ f; d1 Y# b/ F
}8 s" t3 x# w$ K& |
return NULL; /* 没有可用的, 返回 NULL */$ {6 s- A- G% q3 |# l3 I5 A
}
+ K, A+ Z# V+ o, k+ K. N: S% ^. M
void small_free(void *mem)/ S& P$ Z0 B+ B) P% p6 N4 L ~
{- i; A' M9 D; \7 W4 k
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
" [$ f4 A- v# I" u: O" N}3 J1 Y- j+ d6 W
: F$ g! F, p0 m& w [3 ~6 a |
|