|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
8 i. C9 k* p: X: m因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
+ e9 |, i0 \- ~7 J7 z- i ~8 w正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:3 n- j; l+ b& r( u4 H, r' ~5 g
+ p/ x6 v$ a/ X( \0 V5 p9 w! H) b. ~1 K
仅三个函数: ~' P' t G+ t+ j. A
% v! y4 U0 n0 u6 Z1 }3 S9 g<<SmallMem.h>>
0 P$ f6 A! T! u- e! g" p0 U* G( y5 _0 \9 l) J- z
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
: r! ^' ]% L; {) i
. L8 a$ k$ j5 Nvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.- Y, h% ~; a2 d, E& e0 m
分配成功则返回地址,否则返回NULL. b( ^6 V3 {1 e( p p
& d5 _1 c( N2 e1 cvoid small_free(void*mem); 释放内存块.& v/ z/ Q! q& g2 k# Q
# m9 K% u9 Q& m, J6 S$ V-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
. r" \' q6 \ [<<SmallMmem.c >>
: D& |+ ?# e! k: I4 R3 Z0 O) S
; z8 ?% @+ B6 p, S) \$ u8 J/***************************************************************************************************; p4 W$ h8 g9 ]0 r
Small Memory Managment ....
0 G, r3 d. J4 m& K. h& x- {, w Copyright 2008 by David Xie
; P/ s+ n% C" d9 }7 t# ^
! s/ M+ P' z7 R* {) A Last Change: 2008-10-10
# o+ R& x7 W( c/ W' q" T
5 I$ t8 u( n- |+ T. d; d* E ListHead Byte: Bit7 = 1 Free Block+ G4 O+ W |4 \1 ?
Bit7 = 0 Used Block- F* ~2 h. y$ L: `* y& U
/ a3 v1 p% b+ [1 g
Bit[6..0] = 1 - 127 number of bytes of memory block
1 l4 j3 C2 {7 W" L. a, A) w Bit[6..0] = 0 end of memory block
( M, w+ |" z! F******************************************************************************************************/9 c6 d9 H( t+ H
$ p& F( b# A; ~# n `
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
4 Q: _$ F. v4 e4 l* {#define SMALL_MEM __xdata // XRAM
& d5 [ D3 V/ O; }
2 O2 Y) P- W# _! b7 j: a1 I8 n//#define SMALL_MEM_SIZE 256
6 r# g5 X) N8 q) z: V; d//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
9 B# {; \' a P* {5 Y# w
( ]( q, i6 m+ K: \SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];, a# t; g) t6 ?7 ?* H4 b4 d
: c `- U" O, Z Ovoid small_init()$ l6 o; ~/ q$ v# u( t
{- B0 K4 }4 m5 g5 T0 \' `* h5 y
unsigned int i, n, len;
~+ L1 X0 i; H i = 0;+ V- Z4 F) k) u
n = SMALL_MEM_SIZE;4 {8 l+ o* B5 V1 o" p$ z
# W# J+ t" V+ E+ q4 H& u/ x
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */8 X6 R+ H, p$ V- L& p7 }: F
SmallMemory[0] = 0x01;
* \& Z% }" J8 L4 ~ c i += 2;
- o7 L* }) C! B2 z4 v n -= 2;0 h+ o x% g/ h) N2 c
}
0 `9 \( f. V& d) E! ~- d
) b. j3 c. S) n) w: f
! Q' p& B( p& l2 O! B while(n>1){ /* Init Empty Small List */
4 q# u9 L+ {& `; X3 K len = (128 < n)? 127 : n-2;
% Q( r4 ~2 L& P! X% D( z/ f SmallMemory[ i ] = 0x80 | len;
3 q( S* ^: P& e% Q4 `9 F1 b len++;
7 a1 w1 F6 _) ] i += len;7 A8 H2 v/ n' I: p9 A3 Z2 {
n -= len;- M/ x( S6 w7 {# e
}2 n* h# V+ p+ y. e; E
SmallMemory[ i ] = 0x80; /* End Of Small List */
* D, }7 T/ `! \: |. e}* _% D% f& k/ x: @8 M& x. K5 t4 h
6 D# p5 q! ~9 n3 _
void * small_alloc(unsigned char size)2 `9 Y$ D; `' ~+ \
{' o2 J; w" i- @
register SMALL_MEM unsigned char *p1, *p2;
& A0 H( y5 C/ j f# o* x3 G register unsigned char len;& B0 n* B$ F9 k1 J8 n) D5 h
; u# K; D3 g l8 Z8 M8 P/ R
if( size > 127 || size == 0) return NULL;4 o% M0 k. ]# J' Q2 ^$ U7 y
6 M9 V* N( G) e+ N% h$ }0 ` p1 = SmallMemory;
6 b8 ^6 p7 a& [) P0 b3 ~: _" D while( *p1 != 0x80 ){! n9 ?! S/ Q% Q7 e! Y
len = *p1 & 0x7f;
3 q `9 v7 a3 h4 P/ _ }' Q if( *p1 & 0x80 ){ /* 找到空的内存块 */
5 O0 c4 a' t) ]* H- n+ W+ c while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
G0 |9 y0 K. n3 m! ~$ { p2 = p1+len+1;
1 `. v- T# Y- m) r if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */: r" b9 J) [, ?+ L% ^
len += (*p2 & 0x7f) + 1;8 c' n; z- T: Y8 }( w
}else{" N! V" Y% T. \1 L9 N
break;
" C2 O' f$ V8 ?- i }* h4 t( m' K. c4 e7 N" D
}5 L' G3 b- B4 c2 W/ a& o
if( len >= size ){ /* 找到一个足够的内存块 */' ^5 f. {0 P2 f% j6 F" z
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */% f8 b3 Z% E8 @5 c) @! x4 I
*p1 = size;
! M/ G0 K0 L' S1 [ p2 = p1+size+1;
+ {) E6 l2 C2 B2 J2 W, o0 A5 ] *p2 = (len-size-1) | 0x80;3 `# {' d% {0 N6 j, R. v
return p1+1;
* \4 A e" S( ?5 d" F9 D }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
3 Y4 o" H- u1 [8 U5 f *p1 = len;0 a6 [8 E K" F# K
return p1+1;- A) X: t @4 u" e, z
}
% i' G4 Z8 P; H }
5 W- Z1 i+ T3 Y6 | d! d! O! v3 C } |9 e9 Y: z: l4 d0 @
p1 += len+1; /* 找下一内存块 */* L3 v; `' G7 e0 U b5 u9 |5 q5 X
}9 ~8 C" {" O4 l+ }$ `' G
return NULL; /* 没有可用的, 返回 NULL */% G9 ^' {8 G0 L B: z- h+ J
}
; W Q0 }' Y: {% b/ {0 b6 I7 S, X* w" x" }6 L0 I
void small_free(void *mem)
3 T% J( J/ ?% K5 p" n6 P8 w* q9 k7 g{
z' c+ \, ]+ h7 o *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
$ X( S( \6 `$ o' k |6 i}
/ X" ^) y/ S, l: v8 v3 l
9 I9 \ h0 n) s S( f |
|