|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
# D, k: Y O0 m6 _! i/ a, Z因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.' G+ I$ Q4 N. b" ]3 Z R
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
+ p/ _8 Y& F: P/ _. Z$ A' b) X+ H; `( U: \
3 M; R6 d+ R) D+ A/ j4 B* t4 f仅三个函数:0 Y! \+ q9 U- A) o8 I. ~
8 \- l* A, K5 V( l, d6 H
<<SmallMem.h>>
4 X+ Y; j: S& \0 G' S
; P! m. a% t2 Y6 I/ n' uvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
1 x4 v1 y7 S A( _- w) _% u
( v6 D% d4 c: D, V; Pvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
1 Y; V' R# Q% D/ A6 T' Y 分配成功则返回地址,否则返回NULL.
, a& ], Z9 [- w9 v% c E$ g9 G- S' Z% C( u% C5 d4 |6 R
void small_free(void*mem); 释放内存块.7 t8 q3 b2 |' P; u# L
" |2 H% R; z) h+ i
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
: b! `' G0 M. R( E6 E+ a& W+ [<<SmallMmem.c >>; X4 _" n3 a9 _. c) E- m
0 y! o7 n3 r4 v8 b& q) I& G/***************************************************************************************************
* J, Z$ u8 \# L7 I Small Memory Managment ....
9 O8 l+ B! M( L5 P" \7 } Copyright 2008 by David Xie 1 _! C6 L1 u; q- J, w; G# I5 Q$ p6 x
9 y& j( F/ K/ }6 t9 F Last Change: 2008-10-10* W4 D7 @/ g q9 G+ v' B
% `3 u0 Z9 `! v( A/ M
ListHead Byte: Bit7 = 1 Free Block0 t' i5 R, O4 ^$ i' o+ C
Bit7 = 0 Used Block
t: t q* t8 n" f; Q1 S+ f
. t3 U3 X `+ j' \ Bit[6..0] = 1 - 127 number of bytes of memory block4 N% y: r7 S- H$ s1 s# H* e, B
Bit[6..0] = 0 end of memory block
* I* R6 y) k: W% O******************************************************************************************************/
: A# o3 u* \7 d& t- W' E- u3 n. P0 D& t7 b$ a6 ^% J% l
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.: j3 n1 g$ w8 Q6 z9 G
#define SMALL_MEM __xdata // XRAM" Z+ m& {) C# a* v% z6 O
9 {+ k, x* w/ P% I//#define SMALL_MEM_SIZE 256
% a, G1 \: T( c' X# A$ b6 E' V//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.. P! x$ P4 M( \8 Z6 Y- Y
- y2 n# |# C. u) { v' s" f# X
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];( e! A1 G7 j4 U5 \3 \4 U \
) O v- G. x2 O4 k3 p8 U
void small_init()7 {2 M$ X% o6 |3 ~
{! r. Z6 ]$ a# r
unsigned int i, n, len;4 ~3 g0 f- Q$ T
i = 0;
2 G/ g* e; k! g6 @ n = SMALL_MEM_SIZE;8 A. ^. o; _9 J F6 H1 }
) a8 W9 a8 w6 W- B8 J( ?! }
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
, n2 ~9 J' }: \* Q. L& d SmallMemory[0] = 0x01;
- `' N0 ?2 g8 K6 o2 f i += 2;
' z6 b5 |' P+ W, \/ O' } n -= 2;) d9 p/ }7 b6 e+ A
}" p' \. D" D4 h- x
! }6 z$ L j6 f# }
+ `' L; q, M3 O8 G: q$ W while(n>1){ /* Init Empty Small List */. B& a5 T F( N0 _6 F
len = (128 < n)? 127 : n-2;
# l" ?5 {, ~! E$ y/ ~ SmallMemory[ i ] = 0x80 | len;
# W. K! f9 B& l5 `% w. r len++;+ [* d/ L& b0 a7 T7 U# x2 s" a
i += len;
. _2 v" k1 K y n -= len;* s- d' O& _$ p* |6 d. G9 O. O: A7 _3 ^
}
2 Y4 _3 a, Y/ y4 i# k9 m+ g8 T SmallMemory[ i ] = 0x80; /* End Of Small List */
7 ^# t% o9 t5 U}
1 A7 K( ~# o$ F5 f$ l1 q8 o" L
0 t0 s8 L5 q9 T+ X+ Pvoid * small_alloc(unsigned char size). d' D# K2 I- @+ ^1 Z& S0 E
{
6 }( D3 i0 x+ c2 t8 C* N) C register SMALL_MEM unsigned char *p1, *p2;
8 \0 q- m: P9 x$ m' e. r register unsigned char len;
: o5 S0 }2 L) y B# M2 @7 w* b5 i0 O" Z( Q4 _5 r4 I1 r0 h/ i
if( size > 127 || size == 0) return NULL;! `+ Q, F# }% s3 l
2 |/ \; F; l" |) A- S' y9 D p1 = SmallMemory;* Z7 L9 M( c, |, p
while( *p1 != 0x80 ){# E; @7 l4 i7 ]2 t, C% d
len = *p1 & 0x7f;7 k6 U! ~5 ~1 B! L
if( *p1 & 0x80 ){ /* 找到空的内存块 */
1 |$ M2 O- \% Q& ` W$ L while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
5 A& d" F, P/ ?6 O; O! R p2 = p1+len+1; / S1 R" Q3 m4 J8 I: v2 X
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */$ Z2 z" G& ~: W$ X3 ~" I$ k
len += (*p2 & 0x7f) + 1;
- @9 [! [2 R3 f) U# T; p4 [ }else{
" o/ |# l1 T# `7 [4 W break;
- z4 O9 p+ f7 A, N& J5 _ }( }! N$ D3 w5 |( t' r* f
}% j# L$ b, l1 x* ~; A
if( len >= size ){ /* 找到一个足够的内存块 */9 C0 v; s' g. E) O5 L, A
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */' d" u: p, L% p: _. v
*p1 = size;/ K& C. n" X: [* r
p2 = p1+size+1;- l' R! u) H: N8 E( J0 {3 @/ ~
*p2 = (len-size-1) | 0x80;, N' k; Q/ [4 e9 }
return p1+1;
$ a1 o3 Q' P( {" O }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */4 J( {+ E5 r/ c* R* [
*p1 = len;
0 a" i6 n# ^/ ^9 Y0 X. Z3 E return p1+1;
' B* q. {3 Q2 Y" b+ @ }1 A& n% t! h: e
}
' Q* p" y6 j$ X! h: B }( f3 y0 v g1 G
p1 += len+1; /* 找下一内存块 */2 g3 |: E; \" k5 i i1 [7 \6 r
}
{, b" y8 U) `( h# D$ h, m& T7 T return NULL; /* 没有可用的, 返回 NULL */; K0 l+ B2 F$ x
}
. n4 T) d! K- x# Y
; C7 L: R+ N) A% l0 M4 M/ c* i, {void small_free(void *mem)& n( f* l2 ~' Z) t' a4 T! P, Q
{$ w7 y* p) @- _2 b" W
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */0 ]+ F- L1 ^ }1 X: o! |& }
}
4 R: H4 ?0 Z1 ` _! s: s! i
U7 {9 I/ a! O+ Z9 y |
|