|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
. X! M- z: h7 C& V$ m5 p8 A8 p因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.- g1 u% Q8 O6 W" P2 o. j$ r6 g
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
8 r; B) n ?( O% H6 p+ G. h
# R5 t8 J. }! V' E; s R) L Z2 q! E+ K- W& f
仅三个函数:7 Q5 Q6 }0 {( S6 }, B2 U! X& D. E/ r
; M3 B3 k: C3 p' R0 k; Y: W1 S5 H
<<SmallMem.h>>$ Z; T1 V' k3 X8 O/ R
7 q0 _7 t- e& _* C- D; k5 r; Jvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.- f$ D9 ^# P9 t; v
3 E5 Z% E# Q. q. z9 r6 V" S
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
: t& y% x/ m( { 分配成功则返回地址,否则返回NULL.
+ G/ N. u3 k: [. V' i; [
7 L( f4 p: q3 x7 _void small_free(void*mem); 释放内存块.
3 I- H; {0 u, H9 g* i2 \0 B
2 c# l% m( G5 |+ L& N% k-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ U/ e# Y4 P: G* s<<SmallMmem.c >>
: A) T$ v) ]6 e, p. v f' i' p. J3 Q
/***************************************************************************************************; r, b6 `# u R7 o
Small Memory Managment ....
# I* ]' m% W* b( |5 v, o( g# V Copyright 2008 by David Xie c7 @; y% ^* r! G1 M: k- u9 U
# m% j0 ?8 W0 Q2 V/ l! G
Last Change: 2008-10-10" m3 D: ^" v' F! t1 x# K+ Y
/ w! o! a R/ x4 L- L( p. B/ f ListHead Byte: Bit7 = 1 Free Block' t! f+ t$ e4 H! |, S
Bit7 = 0 Used Block
3 D2 C u4 b- n
& F$ E+ ^. O' {5 X& v+ f# } Bit[6..0] = 1 - 127 number of bytes of memory block( p) p# h3 Z1 q+ Q: |4 M/ T
Bit[6..0] = 0 end of memory block
' ^, n* h: |9 K L6 g$ L******************************************************************************************************/+ d1 ]! L% \/ M8 d$ X G3 L
! d# z# v- @/ d: D0 x# H#define SMALL_MEM_SIZE 1024 // 依你的系统来定.- c2 n8 R1 @3 Z7 v4 P; }/ U
#define SMALL_MEM __xdata // XRAM9 R9 L2 i" T) @* S, y
( |$ q- b: ?% @# j//#define SMALL_MEM_SIZE 256& }" A( l' x$ i, J: T
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.% H: C8 ?. Y o7 p: L% G8 P* z+ P
) O& J% \/ J Q$ h$ A
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
( q0 X2 ]. O, i- ?2 a" \( m
* {! {/ V& h% Wvoid small_init()% W: |8 ]3 _# [2 b8 u" |$ p
{
+ G8 q4 s8 z! ?, c) _- _0 O$ b unsigned int i, n, len;, W" g9 _- j1 u0 O+ Y- d4 X8 Z/ H
i = 0;: J) O+ u+ }0 u+ y
n = SMALL_MEM_SIZE;
0 u" q( M, a$ v- \5 u" g( `* s5 z# Y& j. @# c* o
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
' B/ Y' ~% m1 A& `; ~ SmallMemory[0] = 0x01;
% i- v; X2 K3 O# O- g* T i += 2;
5 s5 U% z( X: C4 J Q n -= 2;& ] Q0 b" n+ h8 ?0 o; m
}
/ K d2 ?3 p" m* J' I. E {8 n3 j- ?9 _
( M4 d( }7 N5 U0 t0 j3 w+ D2 `
while(n>1){ /* Init Empty Small List */
/ i" O& W; i# r# t len = (128 < n)? 127 : n-2;! L% ~6 O& D$ j" @
SmallMemory[ i ] = 0x80 | len;$ ~: {4 a- u! s/ `( q
len++;
+ P7 `( K/ B7 u9 |. _! M0 v i += len;
& j+ E4 }2 h" ~ A n -= len;. Q% f& V( l. ^% |% t! g6 d6 z
}
1 | H# b7 O- L' w( } SmallMemory[ i ] = 0x80; /* End Of Small List */. h7 ]0 Z x+ ]
}: F( B- v5 z* |$ N, a; X9 z
+ y5 O/ M ~, S3 x7 B
void * small_alloc(unsigned char size)
4 s7 G0 U0 U' ]9 {! T8 S{) h( y8 y" h' f: v- m
register SMALL_MEM unsigned char *p1, *p2;' P2 M& M/ n/ A1 Q2 I
register unsigned char len;2 y, {! O. q; }: u
/ s$ [/ K) Z& k( g& G* N5 \ if( size > 127 || size == 0) return NULL;
9 |6 o z i7 o
/ m7 `5 E( w0 y5 |% N p1 = SmallMemory;
6 i- w) v0 D0 Q8 z x while( *p1 != 0x80 ){7 _3 }5 D/ N1 k3 L$ L) u% W$ K
len = *p1 & 0x7f;
$ K2 e' Y; m! I if( *p1 & 0x80 ){ /* 找到空的内存块 */
# D: Y- U1 r3 W) V5 O+ Q while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */6 w- T1 [% \, ]2 {
p2 = p1+len+1; 6 h* l; e# {6 N. m7 \' S$ |
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
/ M% |: q( ?; M' ?( J$ Y! F; [ len += (*p2 & 0x7f) + 1;# ~" l; D3 ~, P8 `/ z
}else{
% d8 K, y6 U4 x9 y break;5 p; p, q3 }' J2 ~+ X
}
' w3 y# d6 q& f& ]0 P }
% f- F2 q# j- F' e, @1 ]3 T( ^" x: g if( len >= size ){ /* 找到一个足够的内存块 */
# y6 \7 Z v0 ` Q" f, ^ if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
6 }( X6 ^7 Q9 Z# |* r& ] *p1 = size;
& |6 ~& M0 B2 q. l( ]* ?$ Y p2 = p1+size+1;! n7 M+ n8 T6 g
*p2 = (len-size-1) | 0x80;) l" x K9 R4 ~, p u/ |
return p1+1;
* a% s. [% c& O% }9 {* m& e8 o }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */: J6 j; V: Y/ f5 }, k% }! N$ P& Q
*p1 = len;6 N2 S K5 e0 H. e4 B: Q
return p1+1;
t5 ]1 T% Q# J( @' \2 e }
9 t+ p" Y. a; {6 q: a- z% B }
( t4 L% s; l/ K+ p7 P8 z }
% o3 E9 L# m; h A" C p1 += len+1; /* 找下一内存块 */
( P1 J; i8 O9 k* S* K9 {6 G1 h6 v }3 L2 ]" p' O8 @$ L; k: P6 y8 e
return NULL; /* 没有可用的, 返回 NULL */
2 R( M; K6 |9 o, w) x c B* x} H3 U: {* ~$ r& g8 z; a; @
. f F" b. Y" i7 `& c7 N9 O5 ~: wvoid small_free(void *mem)& I7 u, X; g+ i; t$ `# ]
{
' \& M: k( `# q' _' z- Z. y9 R *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */7 @% p; a+ l- q! P# B9 C
}+ R" J- p6 [ Q S, S( j2 J
; y. i0 H2 B# S8 G) K7 _ |
|