|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
0 v- O# T( z3 u7 u1 n5 y$ m! X因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List., D1 _& @: W5 e+ K; _
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
; G2 F9 R# t* e8 p1 ~
9 Z, Q6 ?* U! M4 @% C' G) [" O
2 ~) s' F% j* t$ ?3 \仅三个函数:; \: [8 q7 {/ j* U/ g# u5 U
- d: z) o6 ]( P- y<<SmallMem.h>>4 h' p( [# d8 Z" Y: d# t. H+ h
" @3 I8 F. t8 Q% r7 Vvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
; b/ {" ^5 [6 z# {/ S
. {& g8 ]( [. l& a) ?9 ]void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.8 j% L& J" g* Y# ]; K0 O
分配成功则返回地址,否则返回NULL.
0 W1 J$ v6 k( Q; `; ]7 ?- A
% X% I# ?" }3 V- D& D( R* D0 K, ~void small_free(void*mem); 释放内存块." J- O; ^3 H3 l# D* w- P3 l& d
( k1 E3 x4 [3 L
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4 T* A0 w. S5 b5 B2 Z% L<<SmallMmem.c >>
, R0 {, h6 ~8 P, n) _& K
9 W: y# L2 y8 E! Y3 f) B9 `/***************************************************************************************************8 n# A- Q/ ?. Q% Q
Small Memory Managment ....: P' k0 ?6 e1 h7 I* a$ c' _' s, E' `
Copyright 2008 by David Xie ; |: [/ G0 M) X7 K8 c
5 R; J0 x$ V7 k7 b, u3 g Last Change: 2008-10-10! k5 n( _% c9 @
6 N( j) U# ^) c' y+ D: T2 y
ListHead Byte: Bit7 = 1 Free Block
! ^- d/ m$ ~6 Q7 b) ] Bit7 = 0 Used Block
" K' z7 ^: y: p$ U; s' a: G8 ?' w* a3 d" }0 d: F2 V
Bit[6..0] = 1 - 127 number of bytes of memory block0 p, o; w$ U. a, ?. q, ]
Bit[6..0] = 0 end of memory block% x" d; N# Y( _+ J
******************************************************************************************************/8 a) o; I, ]: o) g3 J0 a, ^* k
' g% g6 z N7 Y5 B0 n: ]
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.6 ~, J8 s, q$ R b
#define SMALL_MEM __xdata // XRAM# |6 D. n; S! G3 F" }$ Z/ t6 E3 R; @
1 E& o) W3 |" ~0 v+ n* t8 F' u$ m//#define SMALL_MEM_SIZE 256& F$ p) L; U6 x7 O9 r& @
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.4 a* M$ S1 P3 X( n: A7 j
& g5 t2 f& r4 b
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];. V A4 ~' ^& v4 ]- \, `
6 M# ^, ~2 j1 ?# B% Z. xvoid small_init()+ R$ ?5 M H Q( J0 u
{1 S; c% {* J8 [4 v4 r
unsigned int i, n, len;( l3 V4 V# R8 C2 y& }+ T
i = 0;
O t! U& d6 U( H: v. ? n = SMALL_MEM_SIZE;
" N7 P+ P- |+ z. q3 ~1 P% Z+ z, a+ |! X# z
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */+ A+ D6 t3 d- e$ g9 L5 a) s
SmallMemory[0] = 0x01;! ~ U0 s/ C& B2 c
i += 2;9 d9 U5 Z1 s- o* H
n -= 2;0 Z: P3 U& W" L$ Z( T( f
}
! Q$ x' v; S8 \1 |4 O+ _, \" Y" d4 z2 m+ W T( Q" v- v
3 w8 R( H' U& A N# h0 ^. A while(n>1){ /* Init Empty Small List */
3 o+ F" z9 ^- N; R1 }1 X len = (128 < n)? 127 : n-2;/ G- J6 J1 F+ o% c8 E+ @8 d; D8 V
SmallMemory[ i ] = 0x80 | len;. z8 B' ?9 g, Z. @
len++;
+ R3 i4 t: j" M. P! t1 p i += len;
; M4 m/ z9 C( M( Z: U7 P7 { n -= len;4 Z% S7 [8 q! @) I; P
}
2 O1 Y0 R0 ?1 `% D: A; } SmallMemory[ i ] = 0x80; /* End Of Small List */+ S+ |7 K3 h2 o* ~' X" w. L7 m
}+ e I% A# h0 h' k {% w
4 @& G( d# A. S+ R+ t2 tvoid * small_alloc(unsigned char size)) M$ C: I5 L- a2 D
{* g+ m9 O" m0 N( w X
register SMALL_MEM unsigned char *p1, *p2;) ^$ k" }" N# }# N i0 j: U f
register unsigned char len;% n! P$ d4 `" B
/ i" L. v _+ w# A6 R4 h if( size > 127 || size == 0) return NULL;
1 A$ O' K# `" x, B7 v6 T* K2 T! e" X8 s) `. J2 g7 a
p1 = SmallMemory;1 Q9 g3 L4 c8 H. t6 h/ @
while( *p1 != 0x80 ){; t* t' {2 x/ B0 o. H+ k
len = *p1 & 0x7f;2 ~" l1 k9 U1 ]/ b0 k. t/ ?1 o
if( *p1 & 0x80 ){ /* 找到空的内存块 */: C9 |& C* Z1 @2 f }& g: ^- H+ ?
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
! g9 [3 V$ Z6 P4 ] p2 = p1+len+1;
& V& r7 t, M/ F: c if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
! E. q6 z2 |( i len += (*p2 & 0x7f) + 1;+ I0 z: O+ s. E+ h' t3 i: n4 r
}else{9 |! Z- p& i) `
break;8 l. b. L" V% u2 I& e5 Y5 u
}
; U; v* ~2 {8 v }. D' K5 g- G* p8 ^& {* |7 X
if( len >= size ){ /* 找到一个足够的内存块 */: F0 N% p: ?6 g- g; _$ {3 @5 B
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */5 ?' {4 A% }0 L8 U. ?
*p1 = size;
8 q3 R0 c; `7 _% f1 s$ p5 I5 s" w! n p2 = p1+size+1;
' H: r0 S; n' C6 N. g. ? *p2 = (len-size-1) | 0x80;
+ Z2 E% A% D9 y( B- a; y return p1+1;3 U* m, c$ t+ I! a" A
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
$ G0 x- W6 ]# Y! J *p1 = len;/ Y$ Q/ X) r+ t3 D/ ?/ | e
return p1+1;5 U& ?* m2 T5 K2 @: l! r: I1 p R9 K
}! O% x4 F! |7 [6 Y
}
1 ~5 m0 S1 [$ }+ H: J) i }
+ U+ I% b9 A7 F' C5 o p1 += len+1; /* 找下一内存块 */+ a( [3 v6 g6 E
}" R- ?/ P) m! t; a: W
return NULL; /* 没有可用的, 返回 NULL */
9 q$ n$ k3 p) I& a# m5 U}
$ A4 q- |1 ~7 N d+ S% \, y- `& s% z( P$ p2 v8 ^, l, E
void small_free(void *mem)
4 }, I0 y$ \& c6 ^{9 F6 U# Y7 a+ y) ^
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
' G! s: D7 G/ D; U}2 j8 U) f+ g: V
" g! e9 }0 R8 D |
|