|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
, X0 o, ?& F1 A" L因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
" G Q8 L+ U( e& v正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:0 H- G4 u! T6 @8 X, A
% M$ D2 i( h, ^1 w
6 L3 s' h- O0 ^4 u
仅三个函数:
. ^5 t& _. y8 b2 {% A' S
, c* B! n4 v0 J r4 v<<SmallMem.h>>
% E R2 h6 g: \6 [3 ~$ V( x* M, C8 C1 {) ?! m* S
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.0 s: P0 g2 B0 q4 K' q( o+ ^3 k
. s l" N" R; g# m+ ^2 J% Ivoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.. U' s1 V7 u/ M+ o
分配成功则返回地址,否则返回NULL.
$ z* J1 P. v4 T$ G- u; t
* Z9 |2 N- t9 [5 o- P; q; _* B2 Lvoid small_free(void*mem); 释放内存块.8 ^* Y+ t9 I% h+ Y2 {* g
0 g( P% R7 I, b' G9 N! ]8 q
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------8 T# A# m7 k! b" h5 w; s. |
<<SmallMmem.c >>
) R) D& Z0 L( n0 x t; k, l* Y6 Q t" s. ] ]+ Z! J9 s
/***************************************************************************************************2 f- O2 X6 D3 ^$ l1 H0 j& w- U: y
Small Memory Managment ....
+ [! Z& I& R$ D$ { Copyright 2008 by David Xie . B1 s1 q2 E# f
{7 Y2 s; n2 _$ ~* P
Last Change: 2008-10-10
m4 t# }7 E3 A7 g- H0 y' V
[* f) j3 ~0 l6 \0 e ListHead Byte: Bit7 = 1 Free Block v7 ^# v. v; \5 W
Bit7 = 0 Used Block; h$ b4 Z. T1 r z
% q2 k' o: e' b" C$ k8 g/ g: M/ p; c
Bit[6..0] = 1 - 127 number of bytes of memory block& J$ {3 }5 }& P+ r
Bit[6..0] = 0 end of memory block
- \+ G2 |' R" Z" T* S2 `******************************************************************************************************/
5 L+ a. d; D. a. ~% e9 I" ]" d% ?( s, @0 z$ |
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.$ x! W; ?. f* L' U9 T
#define SMALL_MEM __xdata // XRAM5 P6 {. T* c" ~
# @( F. d+ d! V1 V+ B! g7 k
//#define SMALL_MEM_SIZE 256, s3 z; ^0 B6 x
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
& _ v# v/ S! y9 Z* ^$ f- H8 o) e# e8 j. \ \) ~
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
" O$ d. ^. l- L( f& y/ G* {& | O7 }5 E$ b6 j* \
void small_init()! E+ b" l/ F, P
{! j, g% N I ]/ v/ M% a0 m8 `. g
unsigned int i, n, len;
5 v5 ]* t. q0 D7 u' D! j5 M i = 0;
9 }3 F1 @2 m, w; j) M6 V7 X( h: v$ b1 | n = SMALL_MEM_SIZE;
) c3 y. {0 h+ p* x$ G
& Q1 Z( K. K3 K. p if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */) ]6 Q' {4 Q/ M+ O( ~, C
SmallMemory[0] = 0x01;
: m& M P! h5 e5 ^/ L' j6 c i += 2;
. s. _6 w9 F: r n -= 2;
7 e* j$ c- U' n8 @2 v }
: e0 F) e! [# ]& _4 }
6 C5 S* h: s" F8 P0 g; X1 t! u8 Y; y: [1 X: K7 Q
while(n>1){ /* Init Empty Small List */8 t* Z# `; h2 \4 |
len = (128 < n)? 127 : n-2;! H* K( p+ v" V2 p
SmallMemory[ i ] = 0x80 | len;5 f3 n- I3 ~! @2 m1 W( K0 _( l
len++;
' [. r5 b+ a: ^9 ^) h+ Z i += len;& L' ~4 {% q) E. [3 k' b
n -= len;
- ` H- f. i% W0 d }8 {* d9 D u1 @' v
SmallMemory[ i ] = 0x80; /* End Of Small List */
, c, L; Y% d6 Z. w) K& X}
! Z; C! C/ p3 P# c
6 T! V4 f k7 J! A: |1 O" I+ Fvoid * small_alloc(unsigned char size)
$ i7 V t6 m6 _{& L, o# a3 Q+ b; d- F0 c
register SMALL_MEM unsigned char *p1, *p2;& J- V+ Y0 k2 c8 @8 \0 a
register unsigned char len;* q) K- U! c! h5 ` a, G
9 b0 \9 \( u& y, j
if( size > 127 || size == 0) return NULL;. n( T+ P+ R+ ~& V) W) _8 k B
- W# p6 u: O4 A; I: [) U: ]3 Z9 y
p1 = SmallMemory;3 Y7 w8 W. B) Q! l a
while( *p1 != 0x80 ){2 m9 V! Y u5 t9 q, ^$ O
len = *p1 & 0x7f;) V! e, [% l0 p
if( *p1 & 0x80 ){ /* 找到空的内存块 */) \) `' T2 e: V, R% ]1 C7 I2 T
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */5 `, R' G5 `3 \4 L$ I b
p2 = p1+len+1; 1 D' x) f8 W8 O
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
9 W d) t% t3 ^+ l8 s2 k* i len += (*p2 & 0x7f) + 1;
. C( r g- c% p4 q$ p }else{: G* d' Y2 p( D5 w
break;
0 E) g" V$ ^8 D4 y* r5 Q }
- v Q: i/ t( @ V- z }
4 k+ H. S% ?$ _" I: Q! d& f if( len >= size ){ /* 找到一个足够的内存块 *// u1 c! U% J0 D1 v d- j
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
1 `: w% C1 P) n. e, w$ T *p1 = size;
. Q3 T( h; o5 V/ G, ^ p2 = p1+size+1;
) x+ z- W1 l) H# t4 T: q3 x *p2 = (len-size-1) | 0x80;+ q6 _& }# G5 L/ ]
return p1+1;# `8 ]+ j' G7 l" O' [
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
; U: L6 _: Y4 ~0 D7 z7 t/ l. x *p1 = len;
$ T; ^, p2 _! z9 W# L return p1+1;. o( y8 V' p9 R. ?! n4 s" f
}
7 ~8 ]0 O1 C6 Y+ K2 s1 \ }
/ G* }( z, {. [ L9 o. K* S }
! Y W, l' I6 J p1 += len+1; /* 找下一内存块 */) _6 Z9 v l' f, I
}
+ F$ |! p8 f5 W' x return NULL; /* 没有可用的, 返回 NULL */9 w* v2 Q( O& x. e
}* M' w& g' i. K- o
1 X/ u0 r1 m- q$ @ |
void small_free(void *mem)
) }* M+ l; ?8 k! K8 N{6 Y, q6 K7 j. T0 L8 ^' b( ?
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
9 ^+ v' @) h3 h% f' y2 Z}
( l* e! i1 C' M, M2 F
; h5 ?5 @5 Q% g, p- K5 _% ? |
|