|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了)., \/ V: ?- d# j a, }
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.4 M1 s# k6 V' f) R
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
5 u: |8 l# W$ o$ C
1 i8 n6 a ^) T2 `3 T
[( d$ b3 x6 M' L, h& [, u仅三个函数:! n a9 \( o) h
5 X' C0 A/ T* M' F3 U/ k
<<SmallMem.h>>- G7 R2 i3 I6 `
* d7 t |$ O2 [" fvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块. I, f0 i q$ x4 p% s% y
8 W( _* W) s! b. o# L# B; Rvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
8 [$ R+ n' ^7 j% V8 E1 @7 u7 E1 i [1 E 分配成功则返回地址,否则返回NULL.
* P. h! @# j1 B' o% J3 u' h! h
+ Q: I+ D) K/ s/ M' e. vvoid small_free(void*mem); 释放内存块.
1 T9 a# H( j% O/ \7 m; o
, J- Y0 N$ s, N" F; p9 @" L J-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4 m, T3 d' X7 Z* b6 D z+ N<<SmallMmem.c >>
& M% n5 U" b( j1 d, h: t8 A
- R( M& Z' U u+ T. G/***************************************************************************************************# x8 H1 m8 ]' o/ |1 ?
Small Memory Managment ....
( |' f0 U; p; n2 U0 l Copyright 2008 by David Xie 6 A' r* v8 U6 r- k8 @" t- h8 Q
- ?) j* V# f3 u" d
Last Change: 2008-10-10
8 l1 K3 H9 O0 [4 Q) U; E9 d: B O0 c3 [
ListHead Byte: Bit7 = 1 Free Block
) R/ `0 s! c- u& S Bit7 = 0 Used Block% t8 m' w3 B/ c
1 S3 f$ W& h; U; f7 ]' m Bit[6..0] = 1 - 127 number of bytes of memory block
, M( T. h, E! n2 e$ G: S Bit[6..0] = 0 end of memory block
2 N3 j6 H2 a! ~- p( [$ G******************************************************************************************************/
8 ^. [; S& w# R v# `
3 |# n4 F8 F/ j9 P! Q#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
" }9 _: H+ S2 C/ a0 _; u# t#define SMALL_MEM __xdata // XRAM
m4 l& X3 d" I7 h: I/ x1 j& Z- [. R A3 @, P, l% I
//#define SMALL_MEM_SIZE 256( ^8 j! M# \" ^" l C
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.- P/ D7 J5 l5 }* r3 Z- `8 L
, a! o0 a. e" {' k+ }1 ?. w* [( V o- ZSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
/ c( D$ J4 ^5 \5 z9 O6 [- H
) i/ B% l- ~$ }3 B" }8 G' S8 s9 F" P6 rvoid small_init()6 H& ^7 F/ g' d$ }, f0 s
{
3 B! `; a/ Y1 t- r unsigned int i, n, len;- b" F; b! k7 P1 z
i = 0;
7 ^3 m' ^2 Z5 d7 ?2 i n = SMALL_MEM_SIZE;6 {0 N! k/ n% [$ J# m0 H
' o! i1 o4 |! G if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */# G, s2 p* s- H7 i x
SmallMemory[0] = 0x01;9 B( d3 I/ g( y; N. V
i += 2;
$ t" ?, v7 Y6 O( S# b2 } n -= 2;
) k6 H5 ~7 Y; Y" U+ d' G }) h: e/ q/ b7 y" |! U" y) P) i% X
! q9 g1 z( `6 z, P6 |2 Q
6 X* e" D6 m8 H6 ], D1 j
while(n>1){ /* Init Empty Small List */5 e! t' Y, b, _: }1 y9 B7 `( a: ^
len = (128 < n)? 127 : n-2;6 F* s. ^& @9 D6 k5 E6 ]
SmallMemory[ i ] = 0x80 | len;# Q) r; U! ]6 n1 n9 `
len++;2 [) i5 _6 p" m% ?
i += len;
/ \: Q3 x3 V$ F n -= len;
) k4 H% U. [* b0 p4 G, @* O }
: o: B! }9 y; m0 q2 _5 { SmallMemory[ i ] = 0x80; /* End Of Small List */9 g' W. n" D5 R9 h. W, m4 k
}) `5 D# y# T& p+ c! A
+ `. ^" z, L, J$ }8 W
void * small_alloc(unsigned char size)+ n+ @; x9 ?4 w. h- [: z% s
{
3 }: B. v7 ^/ T' U& p5 B) I0 I7 t register SMALL_MEM unsigned char *p1, *p2;: t7 J- d. e, v" m, ~' S5 H& l& F
register unsigned char len;
1 l& @' I/ {5 ]/ u6 d0 c ~, p% @/ w y& k J6 u2 G, e; F. q" e5 u1 @
if( size > 127 || size == 0) return NULL;
& d0 |4 u1 N' U2 O3 m6 y$ |* M7 g. N5 Y% v0 W6 K4 `' i- R9 F5 R
p1 = SmallMemory;& }' [& _) W0 v4 G* q4 p
while( *p1 != 0x80 ){
9 x% z ^* Z4 }" a5 k len = *p1 & 0x7f;
7 g) b: y, P# Y if( *p1 & 0x80 ){ /* 找到空的内存块 */
" c8 A E5 r% @& m+ w8 U* x while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */: q% K5 K! u, Z! ~* j6 u: A) B* e& C2 Y
p2 = p1+len+1;
- G& f' h" Q0 V2 {( X. N$ w if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */4 L, L0 B; b. g4 D+ e7 W3 {
len += (*p2 & 0x7f) + 1;4 C$ ~7 m; j5 x
}else{6 B6 ~# G$ v( I' M' k J$ @
break;
9 ]/ A; | z0 @ }& J& ^: b* O. e, v
}
d$ G* P! m9 t& B$ E# a3 I if( len >= size ){ /* 找到一个足够的内存块 */8 q: j3 x/ g# O
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */4 \. O6 L6 C1 ^5 X3 Q7 i# D* i& }% E
*p1 = size;
$ `$ ^6 O3 y+ n0 t* @ p2 = p1+size+1;
" v6 K1 g; H& \4 |3 o: Q( p *p2 = (len-size-1) | 0x80;
0 R& J! A5 s' a8 r return p1+1;
. c" j' u: V( d! k# F }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
% E; s$ X" |) n+ t9 {: E: c *p1 = len;) z" x( v- D- l
return p1+1;$ @% E) ]. A% O0 h
}
# G/ _/ i: w3 ?; f4 d9 b4 X7 n }
8 U, A; Z7 X5 S( E6 f" { }" \. j7 s$ A& r
p1 += len+1; /* 找下一内存块 */
- s1 b; O3 a$ S, f' O& |4 M }
4 N' v e; R \- B/ m return NULL; /* 没有可用的, 返回 NULL */
: l" z" S6 F+ d! ~! F}% U5 n X$ u0 [" J" i8 h& P6 U7 Z
/ K2 n& r0 b/ A$ Q! @1 Dvoid small_free(void *mem)* j5 n8 G- w+ |2 z; A9 w3 E
{
+ ~, P2 M" H4 d2 O" b1 L8 G C *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
6 R8 s+ u' `/ p" ]2 @ E}
2 I0 q) ^9 d7 o$ r! b- P w6 B
|
|