|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).; k; R* _7 V5 M: G5 V7 [/ n2 q. t- g
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
8 d% O8 i- E& l' N6 d正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:9 _* G4 Q% h/ A/ ^. E c8 Z3 |
$ K& M" q$ V+ m( [7 l
$ `" g7 w2 X+ S+ _+ N3 a& R4 Z仅三个函数:$ O- Z# A: h* x+ k; R
9 u; @% M7 r1 @<<SmallMem.h>>0 l! ~; h1 Z" W, j8 ]) G: c6 L
+ P* S+ Q9 k4 s0 ivoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
6 p7 K& N3 ^$ ?; P4 E6 j2 `0 k, Z8 R7 W
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求. ?* a/ {# L0 D2 J% C6 Q0 m
分配成功则返回地址,否则返回NULL. # j! F u5 A6 j
4 W4 L4 B- _3 |/ f; C7 A8 m
void small_free(void*mem); 释放内存块.* J1 _, |! h! H' s
. j# \! ^" x+ h$ a/ ~+ y9 M-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
$ q8 m9 g9 u% f: t2 n7 u' O<<SmallMmem.c >>
6 k( b- E4 Z. ]1 K3 }: J) e2 n
, [- t8 L% u$ Y: Q% I/***************************************************************************************************" W8 s& X1 F9 J8 |
Small Memory Managment ....
7 v* D& X/ a$ Q2 _% x- b Copyright 2008 by David Xie
4 n. ]4 b* i3 K3 E1 `! `5 X
7 S' {$ q7 i H' |! ], a Last Change: 2008-10-10
^( q) _) W* D6 m* s& H3 D1 a* a6 w5 I# D6 A
ListHead Byte: Bit7 = 1 Free Block
5 ~+ @/ z. J5 G1 X- w2 ` Bit7 = 0 Used Block0 K9 f! R# z" c- e S! x: F" b
- r* Q$ A# c9 B$ S
Bit[6..0] = 1 - 127 number of bytes of memory block( [% u1 o' h3 T
Bit[6..0] = 0 end of memory block
4 X8 ?9 V5 ?, v. j% k3 O******************************************************************************************************/
2 f0 Y$ b& H# G, f& P1 A, c
- p7 y3 M. K1 W# J( z#define SMALL_MEM_SIZE 1024 // 依你的系统来定.! h4 W. R! L8 _$ j& h0 \! w1 }( @; {
#define SMALL_MEM __xdata // XRAM
+ O: W. J. x9 G2 w# U: u4 _2 V$ p$ L" _0 r! {
//#define SMALL_MEM_SIZE 256% k9 U$ k5 m1 ?, @
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.! {+ ]% T% h) W! |) ~( Y( F. P; {
8 {5 d1 P, B5 d' [. J# H
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];3 ?$ G3 J" q- ^! D l, F
C9 w, k6 q% `5 wvoid small_init()
5 K* t5 n0 c$ H' B; J5 C: Z9 }{- P) P9 ^) @2 i8 ~6 Z- x. Z
unsigned int i, n, len;
6 l4 j) L2 R! L4 S5 r* |2 U9 A i = 0;% A' }- n0 S |# c
n = SMALL_MEM_SIZE;$ C; U4 Z6 d4 Y" y
% Q& n; E& t1 x. {; g+ @
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
N8 {4 Z$ g( ] |' y SmallMemory[0] = 0x01;
2 _9 H3 j+ L1 j4 p i += 2;
( y% N; W# @4 m9 _ n -= 2;( r/ a& {5 K/ ?* @5 U
}- }' Z1 V r9 p$ ^; e% a
3 w$ b5 `, p0 e0 ^7 g3 y9 V1 W8 ~$ s. T5 c, ]! z
while(n>1){ /* Init Empty Small List */& E3 b8 |: h4 J' ?& x/ z
len = (128 < n)? 127 : n-2;
& L \. J, U/ m, B7 w SmallMemory[ i ] = 0x80 | len;1 S! B: M" H, K5 M0 U6 a
len++;) O7 \. a! q* w9 F- K2 t& K5 B
i += len;
1 R2 w: s U$ y# S n -= len;- S; `: U( j; g8 F% {
}
4 R, h( g1 F# p SmallMemory[ i ] = 0x80; /* End Of Small List */. c/ A/ H" u9 }- Z& W% X
}. v3 h+ Y$ Y( T: h6 L; F
: `/ P" G R- v4 e1 I" W! V2 C, B
void * small_alloc(unsigned char size)
, _- F B& L' j5 Y" h, B4 q/ ^$ N0 l/ ^{
/ Y- N/ i5 v* \& X8 z8 t+ a' E register SMALL_MEM unsigned char *p1, *p2;! C2 a- f. ?. o7 ]6 x% w& _. R
register unsigned char len;
9 X6 Q: X. z+ X9 z- y+ K- F
' T" c6 q4 i6 F9 e4 {2 l; A if( size > 127 || size == 0) return NULL; b! x0 V4 [6 P$ b( |
U4 ~9 }7 G0 t: g9 S p1 = SmallMemory;
9 j6 o7 Z2 F3 Q6 |0 a: U while( *p1 != 0x80 ){. _ @7 p1 d! o( b
len = *p1 & 0x7f;) |; V* f" \ n+ b. H
if( *p1 & 0x80 ){ /* 找到空的内存块 */ s6 R$ w' t# Y6 L- q* j; [
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
$ r5 e. a' Q6 Y5 n) v. @: ~/ m, [ p2 = p1+len+1; * @4 g0 l6 l6 A7 P( \0 [8 \
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
/ P+ _, a/ ]; s+ D len += (*p2 & 0x7f) + 1;
, d- j9 m5 V X, ^/ |8 c/ y }else{
( S5 Z% A4 m+ ^9 c9 S break;$ }- [# g% x v1 ?3 i' D/ J2 T
}. q1 ^2 ^3 v* S6 k- E
}/ ?) ]. a* ~ x3 c4 q5 `
if( len >= size ){ /* 找到一个足够的内存块 */
. C7 H3 e |! G/ K if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */ N, d1 E. ^5 J5 Z/ o
*p1 = size;* N/ d& A6 e; S* e8 ~ c
p2 = p1+size+1;
+ t, @% n, Y- E# \ *p2 = (len-size-1) | 0x80;, c' [( d: ]6 `. R
return p1+1;7 v7 h& c1 E. U. X o* U) b Q
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
* E+ T+ b% i$ I+ @, R! l *p1 = len;5 l" N. v J9 U6 k, Z; C
return p1+1;. ^& d: F9 [ M1 u9 |' v' x! \7 a T
}( x. ~/ T' {6 \4 K( d2 b
}
4 c9 \7 e3 X/ ?1 Q8 M2 g* L( ^ }
0 ` l" S, _: a p1 += len+1; /* 找下一内存块 */- ^4 M: y% ?# Q1 [, U" `
}; r- V; _# z {1 `/ q: C/ W& g
return NULL; /* 没有可用的, 返回 NULL */
! z: [) p$ k) g! O9 x, C3 c( ]}; S- P& G$ \2 u& p) h
; W( U" e; e* [' T& avoid small_free(void *mem)
5 O$ W0 h; N4 E: } S7 j% ?" z( s{
! P& {$ J0 W- h" W/ {4 l' o *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
/ i* n2 U' b& \0 k4 B: P% |5 [" y}
! u8 @% \( t1 N
& ~9 o' f1 l% w2 |: U |
|