|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了)./ z* E+ M2 b. t3 S
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
+ N) B p3 y5 _ m, k2 r0 A) D8 s正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
- _: W. @% P" m2 m0 M% e
6 M3 W! c. Y, [7 V2 g& a& L" E0 ]* T6 X- q
仅三个函数:
3 D- K* N6 u7 Z0 _5 ?0 R( G) x( `7 b. E" Z. G7 A, R2 g7 j6 a
<<SmallMem.h>># |3 ]& o. S. k& ]% j
$ {$ F$ P" S9 Q: ]4 W3 B8 d' _
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
; n% ]8 B# w$ ?0 |
6 o* Y1 ^6 M/ H3 S3 ?void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
' C/ `0 r& G$ d4 }! O7 ~ 分配成功则返回地址,否则返回NULL.
+ E5 F8 a4 g6 i% V( G. l8 ?7 @- h; ]2 ^0 S' m
void small_free(void*mem); 释放内存块.: }- |( l3 X1 b$ r! B
4 V$ U. X$ P+ z% m8 ^+ q" t-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------! @. Z# N7 A+ Y- f) Q/ Q
<<SmallMmem.c >>
* H+ L: c* t( x( G+ V/ o
* T+ G N( o5 J2 L% m6 W/***************************************************************************************************
/ m5 {& E: k: g9 K) p0 S# a Small Memory Managment .... {( j* d& h+ Y0 u7 R4 }
Copyright 2008 by David Xie ; k9 {" \+ X: O. ~" v3 y
2 C: }# S& \0 m Last Change: 2008-10-10( I6 v; v) C! q2 n ? \0 x8 Q9 I
3 ^1 y/ L, s, c2 T, T ListHead Byte: Bit7 = 1 Free Block
9 Z$ w" d" @3 M& y, b, { Bit7 = 0 Used Block
- w1 P% A/ c+ e& Q: A, O4 h" ^! Q' E; J9 Y2 f |: P
Bit[6..0] = 1 - 127 number of bytes of memory block
+ F5 G6 `/ Z- b9 q) z K6 l' r Bit[6..0] = 0 end of memory block
7 z7 X. ^ F, |& l******************************************************************************************************/2 K6 X6 j, a9 Y9 j
" E1 C/ j1 z9 g3 D* H! Y#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
4 d- N: V3 ?5 F1 q4 y, X) ~#define SMALL_MEM __xdata // XRAM
& r; a. _# }; H; U' b4 O
2 h0 c1 u- L0 |8 q: G3 E//#define SMALL_MEM_SIZE 256, Y0 [6 C: ]; i- E# C
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
3 [5 v( O# K9 ~$ {' }. }* W3 z; V3 g# @# k5 D- k$ E+ k
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
" E" M* \! j$ o2 S& u l* P1 M; e2 w) i- A ^
void small_init()3 ]) F$ G! T8 ?9 M+ w* l
{
2 L6 v/ v U8 U M8 F6 n3 F' ] unsigned int i, n, len;- J* g6 ^& i! p7 ^1 S2 N2 V; M
i = 0;
0 b* Y: b4 w! r: Z n = SMALL_MEM_SIZE;
W& L/ {0 m4 m. l$ C! [0 ]
/ s0 H7 h/ a5 D if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */: Q( o0 c# V. j+ q% P: g; ~
SmallMemory[0] = 0x01;
9 c) N+ Q' |: x& k ^+ t i += 2;" ^9 z C& A0 p+ K' }; ^1 U
n -= 2;* P) c+ Z6 A3 G; W
}2 a# p. `$ {! l/ y0 ]. q, b' p" g7 s- A
) w c4 d' o- Q2 w2 W. } }$ j
5 _1 C/ w- f6 B0 R0 P
while(n>1){ /* Init Empty Small List */, R# r1 d! C3 x4 {/ I* h6 @& x
len = (128 < n)? 127 : n-2;5 o/ K; _' f3 t9 d" ?+ `2 N
SmallMemory[ i ] = 0x80 | len;
2 X* b4 H% X' [# u0 u len++;$ i1 e, Y: a9 X0 Q8 |
i += len;* Y5 u6 U, |" n# i
n -= len;
- T7 j/ ]3 n( X9 X, F) W }
6 N0 f; |0 J2 @# m; C) a7 I SmallMemory[ i ] = 0x80; /* End Of Small List */& d9 h0 _+ }' w2 N3 Z: S
}
0 H5 p) A0 W3 r/ L
+ P1 b+ l6 i0 ^ \void * small_alloc(unsigned char size)
. R' G( b8 `& W$ v/ N9 x{* A: |' c; T( k7 V
register SMALL_MEM unsigned char *p1, *p2;* b" W& V9 l F* ~3 \
register unsigned char len;5 A, u% _- _. k, S
" E7 }4 [/ L/ V' V$ Y( k5 l5 I9 I1 ?
if( size > 127 || size == 0) return NULL;. e: q; {6 }" I( U. a1 e8 H
; H% i( |6 S7 r+ E7 m- [2 j
p1 = SmallMemory;3 F6 u7 y2 W/ |3 r
while( *p1 != 0x80 ){
% @8 r" \; E+ w; o2 H9 Y$ z7 A2 g8 A: Z len = *p1 & 0x7f;& t) J4 S' K% t8 J4 @
if( *p1 & 0x80 ){ /* 找到空的内存块 */6 r$ Y, [$ x. O' v
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */2 M9 X _) w g* c( z/ X7 L
p2 = p1+len+1;
% [- k( g, Q# y3 p v+ C Y0 p if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 *// T, {9 W) H( c: x
len += (*p2 & 0x7f) + 1;0 j# u- b0 i) F: P
}else{
$ k+ B3 \( q6 Q: O) `6 v& p9 h break;
1 O6 U7 q2 [( \2 `% W6 i5 w }' p' n3 o# Q- n% U3 G: z( [
}9 e/ U1 K( W4 k2 R; P& C
if( len >= size ){ /* 找到一个足够的内存块 */7 O; F5 [& L0 Y# z7 W% |
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
9 i0 [! a7 P g8 _; N0 M- Z, S *p1 = size;
) `) G+ p" M4 Y) g, v p2 = p1+size+1;
8 G; b; K3 c5 a: K$ | *p2 = (len-size-1) | 0x80;4 E5 j- ^3 m: _: t: a8 {. _
return p1+1;
! R9 w$ p4 L+ k! z# e) j C- } }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */( f' W9 @( @( ]" w4 |8 _
*p1 = len;6 }1 }3 v& n9 m2 o* u* h4 h P
return p1+1;( y5 q# d+ H0 `" _
}
$ f: C' X9 C/ p: ^1 G }
9 B5 f0 G$ g4 \4 e3 t2 H: Y4 C7 Q }
$ a8 H& J2 f' N7 p2 ^3 y8 ` p1 += len+1; /* 找下一内存块 */$ _/ r- r- F$ n: `, W
}6 ~# ^( @- g: j9 X
return NULL; /* 没有可用的, 返回 NULL */
R% }" ]6 m e; t/ V9 X}
2 N" i$ l$ Z$ K" [! e' A! q+ R! I
void small_free(void *mem)7 r1 ^2 Z6 S0 b
{
* J$ _ v; W' T; G8 |5 w6 A1 a *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */; H6 }; c$ {- z3 y$ N" t! g, O
}4 r" k% W5 n, ?( s1 p$ l" o+ j% f
% ]' k7 F, [. }# u/ @ |
|