|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).+ v2 E* p$ {- D* v* A2 V
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
8 Z1 z# F9 r: l' r' {" P" E# _正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:9 i( m2 M E. y" h$ H: e$ g
$ v9 |! d$ e6 \. F+ b
* s( s+ J) G$ p \
仅三个函数:
8 e; S t. L' E0 p1 L
5 l8 \' q$ B3 e# N<<SmallMem.h>># U4 o( m) V6 j$ p
& G) J" ~0 S& C+ ?2 o3 y
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
4 j$ f1 p7 ]# `' U7 o- R0 g9 y/ b2 [# X' l1 a* ~% T7 K
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.6 r9 h, w) _% b; t! ^
分配成功则返回地址,否则返回NULL. ) R) I# M d; u- E- l I
" d* z( Q- m, j8 J. L/ i" g' X8 k
void small_free(void*mem); 释放内存块.
# l5 D3 v/ R2 M8 q0 o, V5 C* s F: ~* K; B4 ]7 d1 u/ n: |: c# O- a O* F
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------# \1 B9 X3 _( i; M
<<SmallMmem.c >>
' R) Z. z8 f5 K, k
$ G7 ]# \" K1 V& j: `- C/***************************************************************************************************8 ]) a6 w/ i" i7 M
Small Memory Managment ....# t! k) n, S4 l2 e) h
Copyright 2008 by David Xie 9 L! V$ p4 h% n! V/ [' Q/ @' D
# A* w" l: G x# t* v$ p' V* W
Last Change: 2008-10-10 p" a, M: y% o& K2 F4 L
1 e6 Q! y- K4 D( V' B ListHead Byte: Bit7 = 1 Free Block
/ U% o. @) n( J Bit7 = 0 Used Block: v+ G6 @! o& S7 ?0 L* i0 j3 \0 k
$ |- \1 w" K9 ^# S) |; u5 h# R Bit[6..0] = 1 - 127 number of bytes of memory block
+ ]* T z6 @) o6 x Bit[6..0] = 0 end of memory block
_9 l5 d+ l% {) E******************************************************************************************************/$ q9 u. c& E& I/ A4 B
" h H* E: S; o# G#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
8 k2 G& Z9 W5 W5 H& r: A: R#define SMALL_MEM __xdata // XRAM
1 V7 ]3 K4 G. _. \0 p2 T+ @! }
$ T6 D) x# x; R/ |- h7 e//#define SMALL_MEM_SIZE 2562 P. U6 Y# `' x6 R3 E
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
a1 c" v3 h6 {. _& W2 m5 S$ J1 j( o7 P8 a1 o
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];3 j4 i4 `% d2 }
7 m" n- Z: }' v7 U/ k* h' `void small_init()* l9 g5 ?0 Y6 ~- K4 j- L0 w: u
{
3 |; I }1 d. o* M unsigned int i, n, len;
# F/ E3 L; E: @# z i = 0;
: \' o$ M. }* U! ]7 L n = SMALL_MEM_SIZE;
6 ?8 k6 L! m5 P5 \7 X+ _
: P( [! D! ]' G if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
: Q* S1 h% O" y# w( `8 h SmallMemory[0] = 0x01;
5 C9 z5 h1 Q$ m; m A6 X4 v i += 2;/ o* @" Z0 j' R
n -= 2;* h1 Y9 }5 k( ?4 ?
}
3 S' g7 y2 Q; c# m; X
( |' N2 W+ k2 Y1 _/ u( V
2 _' h$ D2 T7 I" x while(n>1){ /* Init Empty Small List */
- x* G$ `* B2 _+ n- |& C" V9 D! |1 } len = (128 < n)? 127 : n-2;
2 h8 m, u5 Z M0 M4 u) [( F SmallMemory[ i ] = 0x80 | len;
2 G7 C1 n4 Z( u len++;6 c: P/ C/ m, v& D
i += len;/ a0 m- v$ A( m
n -= len;' M5 B: e* Z$ e2 D4 @
}5 }3 j+ m; O+ Q/ F6 P
SmallMemory[ i ] = 0x80; /* End Of Small List */$ p5 A! g) ?" ~1 A1 ~7 p6 E3 f
}0 C1 J5 @. u1 ^" K
8 T' Y- C/ m' j5 X, r( Z. o8 Lvoid * small_alloc(unsigned char size)
8 e& V5 c6 E& b; }6 v- q{
3 k4 \1 p/ j8 v; `# P2 U register SMALL_MEM unsigned char *p1, *p2;
- I/ y* \ t# ^" Y D register unsigned char len;
# ?+ ?5 s6 [6 _. B: y
- U7 P/ U5 x) v/ v if( size > 127 || size == 0) return NULL;& Z$ W4 B( S3 q- o% q Z8 ^: n
) y$ C3 H) V& e$ `& Q6 x6 {- L p1 = SmallMemory;5 l- d' z: n; Z0 b( I0 p$ E4 P# t
while( *p1 != 0x80 ){
+ `2 L k8 n5 B7 S len = *p1 & 0x7f;
) L7 k3 @9 y# L4 Q if( *p1 & 0x80 ){ /* 找到空的内存块 */
$ j' I, K: t/ V* g: p while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
E6 B6 n0 E+ S4 o$ c) [: f p2 = p1+len+1;
6 Y+ J5 i0 l! g3 u' H( ?4 a if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */, Y; y0 |3 ]& y' w3 _1 j9 S3 P
len += (*p2 & 0x7f) + 1;
7 _) h+ l- ?* E Q' h+ \ }else{2 a' z: U. }' ]' H
break;% r7 z O( u& Z2 y6 ~
}
, A1 _1 f& S' p6 v" i( J } V0 J0 D; N' @: v2 ]
if( len >= size ){ /* 找到一个足够的内存块 */
& b( O, O, F: p9 v r# l if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */9 n' i# _' d* F o6 z0 Y8 m
*p1 = size;& n" Q+ I9 d: I! ]8 a) S* O
p2 = p1+size+1;
6 b4 {4 C1 t! p3 R3 ~( P *p2 = (len-size-1) | 0x80;
( s5 n/ I$ O$ b# u return p1+1;) R* I5 L5 t j; `5 R* \+ S) U
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
0 U0 I4 H5 m7 q *p1 = len;
( A8 |( S$ N& |2 G return p1+1;
: [% P, E' b1 t1 G4 P# e/ V4 | }
7 Z2 F+ w) Q5 c' x2 o" y }
, ^" z1 w0 w$ v' N }
8 g6 N; `2 Y7 ~7 { d p1 += len+1; /* 找下一内存块 */0 V+ m& A! G5 |1 S) l5 @. W$ P" _# j
}( j# B/ R4 M; _; n1 K8 H3 n. u
return NULL; /* 没有可用的, 返回 NULL */
1 s; _+ p; m [7 ^8 U3 N! N& Z# W5 e}' E8 Y& p) l3 o/ ^. t: F
8 Z% Q( e: ?- U- K; X8 o$ p6 |9 avoid small_free(void *mem)
5 F( y2 \3 y! o% F* i{
7 y2 `) Z) u+ L6 g0 U8 @% T2 | *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */7 z8 z% ~# O: Y9 m6 K1 \( w1 w L
}1 Y# B) h$ S' v" w& H
+ }: ]6 A! P$ }8 y8 | |
|