|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).. b" D1 u- }! R' b+ | w' Y
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
& x& X0 L5 n. g% a: z$ H正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
% P% j( P7 ~, B3 O; t
* W6 c& Q7 u+ e' W' d& Z7 v( G& X4 M% H0 {1 Y
仅三个函数:
1 c; c- X: r t& w) w, D3 S _
6 O0 P+ ?2 k v4 w- ^<<SmallMem.h>>
1 S. }$ B+ k! C5 C$ M; W4 o m$ G
3 @7 b2 y$ I) p8 c! D7 m9 [; h& ]void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.5 p+ P$ W% X; \+ D/ C
3 O/ Q0 w7 x. c- S% v$ F& j; j( y9 U
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
, p! y! T' D+ Q 分配成功则返回地址,否则返回NULL.
1 t6 E# \# |4 i. t. r6 J0 Y! P) `
void small_free(void*mem); 释放内存块.
$ D+ g+ g( u& ~4 s9 f3 ~2 T0 j5 B7 E0 f4 C* r' v
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------6 J' Q1 V7 W0 o Y8 v i6 q
<<SmallMmem.c >>
3 t& l5 X1 h3 @
4 v3 }; ~. s Z2 K2 ?/***************************************************************************************************
$ n8 W: j' S5 h6 l5 { Small Memory Managment ....
! W4 x! _, \8 W1 Y1 J Copyright 2008 by David Xie : t) B2 @1 V' W- \* ^- K' G4 q# {$ o. p2 x
9 ]2 g# t1 `& ~! a Last Change: 2008-10-10. y, g- x4 Q& _3 X3 s/ e1 {
8 R4 t2 m: z9 t( Y% x# u& d
ListHead Byte: Bit7 = 1 Free Block5 |1 {* b3 E/ u& ^
Bit7 = 0 Used Block1 O. q$ C) W( }/ U
5 V3 i9 K& n: ?- \
Bit[6..0] = 1 - 127 number of bytes of memory block
% F$ X3 N: X2 u1 @3 }$ w# V7 \' K Bit[6..0] = 0 end of memory block o7 | {! q, X$ S; I
******************************************************************************************************/
Z+ Y1 ^/ u2 X4 H
1 C: A+ f6 X3 U0 A6 a3 v#define SMALL_MEM_SIZE 1024 // 依你的系统来定.% \# v, m6 v3 Z* O4 x/ W% k
#define SMALL_MEM __xdata // XRAM$ R8 c5 J4 j4 C! q- i9 T6 c
7 U/ J( q+ R; r; w X; X4 S//#define SMALL_MEM_SIZE 256+ n I8 ~6 m! R0 F: s9 y
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
2 P$ C, C3 H) L6 N7 S- h8 [3 O/ L) m& l( b9 [/ z" J! H
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];" |- Y1 m( z2 H5 o- \
+ B. E0 w7 m/ P0 \& r$ Y3 ]' pvoid small_init()
+ O# j% e4 Y# S) G, @" B{4 p" N: K. M, [( g1 j3 G8 n" b! C
unsigned int i, n, len;
( x7 U- L. ?6 n, A" b# E i = 0;8 _+ _. N4 @: S, o
n = SMALL_MEM_SIZE;' H$ k4 U2 f% X# c: g7 \
' J( I- p+ r3 E! c# I; e6 g- Y
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
$ u! G* y2 {9 @+ d SmallMemory[0] = 0x01;9 B' [7 q5 _2 n
i += 2;7 ~0 N) {7 u9 U+ O; K8 ?
n -= 2;
* o1 ^& w6 J+ {3 C. T0 P7 G7 x& u }
) O( e% K, t' Z# j7 [- I9 T( |" K3 {+ q+ W$ d, i; x J& {
, m4 P( p8 n4 {$ x$ Y, c while(n>1){ /* Init Empty Small List */
7 d0 {# a) ~# X( S0 F/ H( {/ a- B len = (128 < n)? 127 : n-2;
, F6 l7 V3 m+ |7 W, ~' j SmallMemory[ i ] = 0x80 | len;
5 S( ^2 m. U( y4 S. x: j% l6 r8 { len++;* C5 s! o: V. X
i += len;
+ K# Q& v" R' G* T" J n -= len;; s" x( g4 k0 y9 F- W: J
}
0 v# j7 Q* q- {0 ~+ J SmallMemory[ i ] = 0x80; /* End Of Small List */
V0 r; n/ h$ S}
; x' \! x* V2 c6 i: O. ]. \
\4 O/ j- a) Y4 F4 mvoid * small_alloc(unsigned char size)6 s$ J7 z& n( g2 Y# {1 r1 T& h
{
; m/ p8 n" m* X register SMALL_MEM unsigned char *p1, *p2;, p' m. `' P) Z; \& M2 t
register unsigned char len;
5 W1 Q4 `: h0 ?4 r+ P1 X& Z
" Y% {# I8 k' ?9 A: ^- ~$ Q2 w if( size > 127 || size == 0) return NULL;
@8 ~+ h, M# c- s; {5 ~# x+ r1 g9 d8 p: O6 O" Q. g, s% j
p1 = SmallMemory;
& C1 s6 T0 O/ x% R. O4 P$ d1 J* X while( *p1 != 0x80 ){2 s5 E4 R) K& L& ~5 r; t% o1 B
len = *p1 & 0x7f;" Z2 |( U. E& \8 o
if( *p1 & 0x80 ){ /* 找到空的内存块 */
C1 h. Z5 j* k, H' s: w3 q while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */. K% ^+ b% c0 F5 M
p2 = p1+len+1; & r' J- d! O0 D3 u' z
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */5 y& ~$ G, M7 ~, Q7 I4 f) L
len += (*p2 & 0x7f) + 1;8 C* D% m$ B; o$ _' R
}else{/ H% e2 z+ r( ^' o
break;, l2 N/ Z" u5 l. D. w
}9 b/ z. Q) Q! J8 r8 E! ~9 P
}
; H& ^* A; s$ Z1 u5 v R if( len >= size ){ /* 找到一个足够的内存块 */
- R( l1 \, ~4 s8 r" O& x% q if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
8 ?% y0 V2 B+ u* z! s6 f *p1 = size;% ~, x4 q& U' d& X5 F0 i) q
p2 = p1+size+1;
) s$ ~) k4 h, Y7 I* y. E1 d *p2 = (len-size-1) | 0x80;
; G; U1 }$ I! ?3 a: o3 X1 j return p1+1;9 @# }# K* I' N8 W& e9 W& e
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */ C8 d$ P6 K- g5 r( e$ A. R
*p1 = len;
) q5 t. G* n* L- @' c+ w+ x return p1+1;
6 h4 B. y$ `1 z6 R: ^/ s }
1 Z* T5 p8 [8 C }: v- a+ `. y9 u+ n7 E
}* Q, }6 s" U9 D4 W* w+ o) F
p1 += len+1; /* 找下一内存块 */; u0 S% v# c3 o) |6 }/ X% d) C& K
}
5 Z% s2 `4 m. J: A7 S" T- U3 x return NULL; /* 没有可用的, 返回 NULL */" B G( w" t( ~& n/ V# y+ w# E
}' x! `% t& V" e; D$ }
* J/ k# Z4 V6 u' T3 A" P: j, p& bvoid small_free(void *mem)
: x& i% P! F- Y' @4 f6 v6 I{
- \4 N$ B; B' u7 N2 I7 j *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
5 Q! j4 \% p! K4 H! A}4 b' @" `3 n- ?6 {
$ P1 M" D, e* I3 d$ R) f9 q3 I9 ?
|
|