|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了)., _/ \$ T0 o+ o8 j4 S
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
3 P% `9 z: ?; b. k正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
. U1 y$ d y. A) h8 ~
1 v% x( G5 |' w( f" ~# x( x2 N5 `, g) W7 p: ]. @
仅三个函数:
% p9 b% N9 y; q5 j1 A3 ?% u
4 D5 N: X% m. C<<SmallMem.h>>
3 a8 @% W7 _5 u" R" b; `5 f
5 J# J$ i9 S7 Q {. S# Y- nvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
5 J& x5 l$ P0 ~+ E: ~: q- l4 ^7 h- M
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
2 }0 s0 {: {( @& ^& Y 分配成功则返回地址,否则返回NULL.
5 i* w8 z, G/ @+ }( w
% _; O+ _0 a5 A. Cvoid small_free(void*mem); 释放内存块.' v, z, B+ L8 C! s! w
. `6 Q ]' v2 I3 m( s9 [ S-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------% O& s$ B9 ^' w, S) J
<<SmallMmem.c >>' O' G+ R: \; x* ?: X& d2 x% Y
; Z- y. l4 K# m* A4 B, d7 I4 e4 F- q
/***************************************************************************************************
6 O: |6 Y6 u8 \1 H" r( v! ~# G Small Memory Managment ....
6 ~9 C% T% ~4 t: L Copyright 2008 by David Xie 8 M9 }4 s" F+ M3 _
+ ?) U1 U4 N. R* S' ?
Last Change: 2008-10-10- B, H. @7 h* |- y7 B
# S- f& M# B$ W4 {; ~# b- Z( y
ListHead Byte: Bit7 = 1 Free Block
) M1 i+ k+ N' u2 {, z6 Y$ y Bit7 = 0 Used Block# T1 r( o+ Y5 b7 G. Z2 H0 P( W# w
% H1 _6 N1 ?) B; C0 x3 A Bit[6..0] = 1 - 127 number of bytes of memory block
- P" k3 O1 x. _8 n* X; u Bit[6..0] = 0 end of memory block3 j6 ^9 P: k \* k0 @5 o. G
******************************************************************************************************/
+ p3 u, U7 q9 E* I: Q% U/ r2 ^, j7 L
' Q" j1 ~4 d+ `3 y4 O3 ~; f6 a+ K#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
* s) A/ `- ` x9 A+ n$ m# I#define SMALL_MEM __xdata // XRAM
5 W& P# r( P, y' I4 z" Q' @) m
2 Y& c, F' G- b( D0 A; ]' ^//#define SMALL_MEM_SIZE 256
3 f0 \2 h7 Z1 L$ Q( K//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.! i8 L- E) U$ K: x: U b2 I
4 X/ ~9 l& t0 L) O/ q7 [SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];7 q5 L; M/ q5 m$ {. v
: u7 H3 j0 X" L
void small_init()
# H5 q5 Z: _, r' d: u{
+ X1 t2 U8 n0 ^, G% |/ c unsigned int i, n, len;/ F( ?: M) t! e% k
i = 0;
9 {/ v5 k% V: ~: l n = SMALL_MEM_SIZE;
1 @6 w& _; ~7 D3 |
: z0 Q, M$ z" K if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
" Y, Y6 p* m+ D, i0 m+ m) E SmallMemory[0] = 0x01;3 @9 c: B# I# q8 A; Z
i += 2;
" X$ r4 V2 W: i+ s n -= 2;- {( K4 U: ? }
}: s$ }- J, t; H7 k
. W: P& K# [% h/ t& H. p
2 J. C; `; v' T* b; P7 `& w; _ while(n>1){ /* Init Empty Small List */
% D C( ?$ y) d5 Q! J7 @; q* r6 p) B len = (128 < n)? 127 : n-2;& |$ P- V" |' N! P1 _& ^
SmallMemory[ i ] = 0x80 | len;2 p2 X# }$ I( w+ T7 `. X+ Y
len++;' ]! [8 O$ Q \, p+ I2 T/ m
i += len;
; r1 l9 q% u f) ]" V n -= len;
3 k, l5 V) X" L$ n# [+ Y% F }- h) ^# _7 i; G+ j; o- e
SmallMemory[ i ] = 0x80; /* End Of Small List */8 h4 A5 N* o i0 Q1 L3 I5 Q
}! @, E' \, o" r6 O% [
4 l; ~/ o# D: i2 Nvoid * small_alloc(unsigned char size)
/ k9 e3 B& F( J6 a/ |{
: D% s/ M! C. x$ B2 O( o# ? register SMALL_MEM unsigned char *p1, *p2;
$ }7 T% z2 g3 O, [0 } register unsigned char len;
& X w9 j& E7 o! E/ V# V$ R% W4 q x+ K" l9 ]: L" y! K
if( size > 127 || size == 0) return NULL;; Y4 F* J2 n- P' ~2 v
: | ]4 `, s. a0 o: }' K p1 = SmallMemory;" ~; c C- B* R) H6 z
while( *p1 != 0x80 ){2 r$ g! P/ T! R; F, h/ T
len = *p1 & 0x7f;4 p: w0 u" v- J! f8 m. Z
if( *p1 & 0x80 ){ /* 找到空的内存块 */7 |- g' y! e7 g
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */. _% U& Z1 {/ a+ G9 V/ a
p2 = p1+len+1; 7 O" G: j/ l+ a( a
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
2 U/ E1 E* X! m/ t len += (*p2 & 0x7f) + 1;; m7 a1 W* |$ x! Q, u B
}else{
% F" X6 o! D5 P break;2 a0 T% o% Q7 a1 _2 b
}
1 E: d. `$ t3 l% s& y! v( E }, n, T2 t1 ~, P9 g4 j, h# C) p$ e
if( len >= size ){ /* 找到一个足够的内存块 */3 d. L3 w7 P' y! ?
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
* J& A( v. h9 ?+ ]3 r *p1 = size;
5 {3 e+ b" {0 ?! ` p2 = p1+size+1;( E1 h3 O& b) y3 {2 Q
*p2 = (len-size-1) | 0x80;
6 h4 U+ q1 x! V* v return p1+1;
* X- Q: }$ t4 ?, C* C3 u5 \) S }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */) g9 W F$ b9 b: B+ C: q: [
*p1 = len;
# Y- I. j5 k* Z, r7 `/ `, U; ^ return p1+1;' Y, h+ ^( y$ S* f
}
$ Q( \4 J7 w% P- P+ v* t# u }
( A6 [; N: n$ H }
: [/ Z5 p4 p) w3 W* F/ A& T% v p1 += len+1; /* 找下一内存块 */. s. S. ^, a% N* [$ C, A2 V
}
- s! A/ O9 ], D0 Y/ L return NULL; /* 没有可用的, 返回 NULL */! S5 n- M4 s2 a' U
}
8 z2 ^/ }2 a6 j; l
: g3 R1 x% \* |4 ~2 y' [void small_free(void *mem) w7 j9 a- d/ M$ y: z$ I
{6 }/ U& b% H% R& k1 W1 ]
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 *// a$ M* f4 k4 _
}
7 P/ _* o- t# O
" c5 @4 e+ d& x( N2 g4 I% M |
|