|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
" m" X2 e0 A& I- q因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.0 o' R$ c, L) \3 u2 v
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:7 {2 _( O2 n! u0 M0 s1 |% I0 `
5 u ?7 T% @( c( s
M; O; P5 t) i, `: q* e( J+ y
仅三个函数:
1 V A K* K9 h9 Z' d* Z; m( M( Q3 m
& w9 }. H s! p$ q. U1 E( y6 w) `<<SmallMem.h>>
7 ^2 {; F; W! b( J- ]
`" `$ R* k$ m- Rvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.* N$ q4 Q/ K0 I+ N$ R
) q+ [7 ~. V( `3 t- T
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.3 G6 V- @9 `# z$ l0 {
分配成功则返回地址,否则返回NULL.
+ j# S+ j1 M; V" {! a: h, f8 u' p% P( p8 Y$ z( Z, c9 O( q
void small_free(void*mem); 释放内存块.
/ |! {7 S& E0 |" q) o9 Q! E3 M0 l4 X# z8 G- x7 V2 ~0 c
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------% z! G) S, U: k% v
<<SmallMmem.c >>
! q9 H% i7 O! H
* l5 B* n, G$ |) ]* \- G/***************************************************************************************************4 K/ p% q7 x9 E9 U
Small Memory Managment ..... W1 E: v s9 H( t$ e
Copyright 2008 by David Xie * B) a7 p0 J% G7 w1 Q/ M. o v
5 ^; h' o3 D: x; Z( |
Last Change: 2008-10-10
& U) [+ C, E' [ a; V( E0 A
7 i5 O! u' l9 q0 u% \' v7 }; N ListHead Byte: Bit7 = 1 Free Block* R7 I0 B3 r# P2 k' M3 u0 t
Bit7 = 0 Used Block
# h+ t- A. G2 }0 b S, u; M' W7 P* ?8 R1 s n
Bit[6..0] = 1 - 127 number of bytes of memory block \# q4 L8 e" _, O0 o
Bit[6..0] = 0 end of memory block
- m5 w6 M" s( L0 f4 X******************************************************************************************************/
9 ~3 r5 L& V# Q) ~" v- c4 L( Y0 f& D, W( t8 `' ]
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
% C7 g' D1 G+ V& G#define SMALL_MEM __xdata // XRAM
4 q: ~* z' ` N4 i" t e: T' p$ [* x$ H0 D0 j" w
//#define SMALL_MEM_SIZE 256$ E+ F6 p$ a3 g
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
' A$ c' j3 d+ j1 r- q0 A" b p; u, w" b: V
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
7 }# B4 l% f5 U: m
+ K" [' l) [' ^6 Avoid small_init()' ~) }' E1 }7 S" J# L
{* ]7 ^. t( w% ^6 a0 n* F
unsigned int i, n, len;
9 X r) P% F0 D6 v; c6 R9 S i = 0;9 K" o7 \* n4 v: U' ~1 G4 i1 a
n = SMALL_MEM_SIZE;$ b9 ~- m2 h6 y0 x. Z d/ a! q
! I# [/ V! O+ q* W! |4 @7 _
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
0 Z! ?8 ~/ |, K: p+ H9 V) {6 ^ SmallMemory[0] = 0x01;
1 r1 r- ?) T6 @, E, m! i2 J7 M i += 2;( y) {) m! A' X: A
n -= 2;% K0 A0 ]3 t1 a; q3 ~" D- G6 r
}
8 s \4 d7 A- g& Z) @
7 \* X! V% B8 B6 E0 Y! K! X8 N& H0 Z" S7 E; R3 R
while(n>1){ /* Init Empty Small List */+ r' w7 y* e9 {, m) @$ q+ _
len = (128 < n)? 127 : n-2;
- e( D( j. \: q1 z/ B SmallMemory[ i ] = 0x80 | len;
, i- p6 h' A# K5 ] len++; |- {# y7 n- _6 X+ @& k0 ^
i += len;
* }; h# @& d: T7 z1 f$ ? n -= len;8 ~! S' [4 `! h! T
}. c2 H. g5 X! @6 U& ~/ G
SmallMemory[ i ] = 0x80; /* End Of Small List */
5 H8 o6 ~) }* U. s& z}; V% z. o) F9 Y$ Z# c
, `$ q) X5 U1 H/ J) i) z" ovoid * small_alloc(unsigned char size)
- z+ T* w( _5 S# o# D9 d{6 y8 L) t$ [! ]- N! Q
register SMALL_MEM unsigned char *p1, *p2;5 b7 X, C) B8 ^9 ^ p
register unsigned char len;5 }6 j8 s8 @6 u
* |* T. y- r0 E: b0 i% q A
if( size > 127 || size == 0) return NULL;
M! u/ r' U1 ]1 B& _- {/ F1 Q$ O1 T& {4 e- S* L5 H
p1 = SmallMemory;
" V, E# g+ k, n% \, b* x while( *p1 != 0x80 ){ @& E5 k; ]+ y ~
len = *p1 & 0x7f;% J1 [0 n6 b I
if( *p1 & 0x80 ){ /* 找到空的内存块 */
# g) H& O1 B/ j while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */+ N0 \: {, \ W8 t' [- O* L
p2 = p1+len+1;
! y p. n3 ~% u9 s9 S: w if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */- r( ^6 i* k$ ?
len += (*p2 & 0x7f) + 1;! v% q- E9 v8 E) [9 S
}else{1 z, B7 |/ X" g5 o- ?
break;# f' C; r% O I( o- {- N; g i3 g
}" C4 u2 ]: h. E; H+ B- t0 z
}& h2 ]/ y$ ^( l' y
if( len >= size ){ /* 找到一个足够的内存块 */+ N# M1 a5 S# h% v
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */" S9 o, K* P# s' _! X
*p1 = size;; ~0 ~& J- N3 Q, b$ o3 {1 X
p2 = p1+size+1;
' @4 A7 V! G: c4 T( u Y *p2 = (len-size-1) | 0x80;) H/ f: a6 H; u$ _1 Z% I
return p1+1;4 O3 }/ t1 p& i
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */( p! ]9 h2 D$ t8 K* N
*p1 = len;
. `6 O# H& E! S return p1+1;3 _2 l" z+ e& ]+ V( I
}% M6 J6 {: e5 \- _( y+ l) S1 n* H
}
, Y* {) u6 c2 W }- l& V, K# J9 v( q$ G
p1 += len+1; /* 找下一内存块 */
0 s% x0 x/ e% s( K. R0 E4 ] }
8 H1 B& _' @, X5 l return NULL; /* 没有可用的, 返回 NULL */5 K" x% N7 C6 w
}
9 I/ D, M" N0 C1 |. d2 ~$ B
; O. w1 ^7 [( c& r8 C6 S5 \void small_free(void *mem), A! Q! F) `9 N x" d
{7 K( }7 W0 w, g" B
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
" H I+ G6 F j& b* S8 [}) U1 V ]! d; s0 U( c, D
( }/ ^/ J7 O6 t
|
|