|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).) L1 G/ f7 d7 K6 u0 v9 z
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
& {) t E7 k" q8 x! p) A4 j正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:. n) I, }; K/ x7 V: _8 e) @
* u' [8 f5 Z6 L* [% ?+ s4 |0 H
/ U7 U" |! \% L9 V* A' Q0 r仅三个函数:$ r# b! Z. S( }0 K3 y
7 T) O" W9 h. H, P* Q' w; }& x<<SmallMem.h>>
1 R3 U6 ]" B1 {4 B" ~/ P0 G6 n' ]7 E5 R4 d$ w( w
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
" z4 m" P2 i e% g( w; K' D" x- Y( _, c Q! g
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.( W, X8 p& a* C( S5 W
分配成功则返回地址,否则返回NULL. / c% J% D# q4 F) z
, X/ K; _. {: Y9 S7 ~. ]
void small_free(void*mem); 释放内存块.
3 U6 \) }2 k. a$ q" n; ~* P; E% N5 p+ e) \. ~# z
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------4 t. P G' D- ^9 R+ g
<<SmallMmem.c >>$ c4 ]/ k9 @ s
7 \7 \& z9 p+ {. i
/***************************************************************************************************6 r' ?) Y: Q4 f) a1 Y% t: m# l% Q9 r
Small Memory Managment ....
. H4 Y+ X# [+ @% D( I" ] Copyright 2008 by David Xie
+ Y1 e# @2 `9 b% P
# N2 _$ a, x# i, N Last Change: 2008-10-10+ ` N. c# q& d4 v
" Q; {3 `5 r; B7 k& [* s ListHead Byte: Bit7 = 1 Free Block
9 z, M8 |7 F/ \, h- l, Z Bit7 = 0 Used Block
) G* c) h7 P4 ~. t
1 J: J& Q. ^; x0 G Bit[6..0] = 1 - 127 number of bytes of memory block
& K& [" m N4 d& V Bit[6..0] = 0 end of memory block
0 d |, o- V. j; K, T8 `******************************************************************************************************/ `, w- T; v$ [2 p: G
5 D/ `2 l0 Q* F, q3 u1 w1 v9 x8 q#define SMALL_MEM_SIZE 1024 // 依你的系统来定.: a N- A( O* ?5 g. B
#define SMALL_MEM __xdata // XRAM" i0 _: T3 f$ d
# {4 b. A) ~% D//#define SMALL_MEM_SIZE 256
: K% W& G, o4 H5 U9 i9 U//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
6 P7 ?+ V" Q) J5 R8 f* w+ M n: t8 G+ ^$ f7 _6 I% T
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];) Z) @, p% R% u# T
+ J2 b& v0 v) r: g' L8 v- n: s, g
void small_init()
" u, f& h8 B( \- w{, E" L" g0 a8 C
unsigned int i, n, len;: Z. D6 Y8 l% j
i = 0;
! I( V1 H/ ]# P& ?! a n = SMALL_MEM_SIZE;6 M: ?, ~( w9 @1 f3 ]
) l. w" b k# P0 X) w2 n0 }, n, [
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */+ [. C4 \) Q# P. r; N1 [1 y
SmallMemory[0] = 0x01;
% U9 c# P# l2 q8 T2 q* j2 Y i += 2;
. W5 X7 x/ ?! T3 x n -= 2;/ p% {: e9 }+ B4 S; I0 [ X4 [
}8 b; r7 l$ c" R1 R
' b+ I+ }" G7 S% ]8 g9 H$ U
2 U$ @2 t; b0 N0 C2 H6 E: \0 z while(n>1){ /* Init Empty Small List */3 Z& V- K0 ^. \- n" p
len = (128 < n)? 127 : n-2;
# O R: ]* C0 H, H0 _ SmallMemory[ i ] = 0x80 | len;
, m) Q5 y6 p- a3 Y* H5 Z len++;% Q; {0 e5 \5 k6 n7 S. s, t
i += len;' G8 S0 M. [+ C7 F
n -= len;
" f N3 [# d: E8 f) ~6 J* ] }
# l5 r& ^( D1 D- F SmallMemory[ i ] = 0x80; /* End Of Small List */
1 r, n+ d" T& q+ U( k0 H}% a$ e, M% v! ~7 U# | U
+ o8 r; H6 H" a" D% L0 F- ?& `' p/ r" qvoid * small_alloc(unsigned char size)
& _1 f' ^: m3 r* P) e1 `9 K{
7 {/ y" l/ l! O1 d register SMALL_MEM unsigned char *p1, *p2;
8 l7 {, z# h# X8 { register unsigned char len;
& o8 W- {" h" G0 o. q
2 T6 \ W8 T8 x. Y! `+ X) z if( size > 127 || size == 0) return NULL;
9 o# J a s, Z' e
( O+ ?1 ?- R& a. q p1 = SmallMemory;
# y3 ~: s) |: ^/ B x while( *p1 != 0x80 ){
; N0 M, K, }$ ~5 N: _9 c len = *p1 & 0x7f;6 [+ v6 n2 V2 o j( n7 o
if( *p1 & 0x80 ){ /* 找到空的内存块 */8 i A; l0 E+ N8 u9 T
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */+ F" s6 P. r' ~& H: R! H
p2 = p1+len+1;
7 h; ]3 j4 |* y/ x) d9 K if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
$ V7 r0 `0 p) n3 M, a len += (*p2 & 0x7f) + 1;
4 l; Q4 f6 }" H0 @ }else{% B( y0 c" U4 E& o+ Y
break;+ n- S g( Z0 U# P6 O" _5 c7 h
}7 P2 j: Y5 A3 v2 E9 N
}
+ P) G) D# R+ I7 D+ g if( len >= size ){ /* 找到一个足够的内存块 */
! k7 Z) G9 n1 s0 n: ]- A. ? if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
4 f$ F x: I8 Y3 E5 i9 u *p1 = size;
* c! P/ n5 ]% w x, y p2 = p1+size+1;$ E% \) ]/ Y/ c" j Z# r7 y9 O
*p2 = (len-size-1) | 0x80;
# S6 P: d0 b* e return p1+1;
. M. D; R; ~' _ {" \1 O9 O1 J }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */; v1 [# e0 I3 ?5 g
*p1 = len;
% y& M9 g4 F5 W return p1+1; y- S- h& _; L7 [% l$ ^
}
( r2 l; o# P" c( i8 m }9 u6 O. S- a5 u* Y
}
, E; R: J. t/ f% ]' X" J2 h4 y& e2 n p1 += len+1; /* 找下一内存块 */
5 Q( |1 t) j/ e }
3 l7 R$ |0 r2 K- U4 f return NULL; /* 没有可用的, 返回 NULL */
5 @2 s) N: K0 w7 I6 t9 P/ _4 E}3 F# O. G3 T$ Z- f# w' O) {" e* `6 ~
# C4 j5 \ n+ A
void small_free(void *mem)" x6 }9 a. n' k- I
{
* ~- J- G8 L/ i *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */; _! `% _6 n1 }- L i$ v+ C M
}, t% L; O, c4 _3 v% @6 M
5 Z H4 ^) J. i I7 s% F* X
|
|