|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
5 r# R' ^! S! y* y5 e: c因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.& Y& P$ A0 l$ a# U0 ^6 y3 n9 g
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:) d2 D5 }, J2 H
9 O) ^$ K) |8 `3 k5 n
5 q9 Z- q% i4 i& u仅三个函数:
: F! Z4 o* J& x0 G
7 e* E/ l. i5 u$ `# x<<SmallMem.h>>
) P x. G5 W: r4 q( M* K# @- R$ N1 t3 c. @ Z
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
% \/ v' i; P0 V/ l7 Y5 U2 s! P3 u" _- L$ |/ c" Z! Q0 Y$ f' L
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.% F! Q( [3 a8 L0 M( U
分配成功则返回地址,否则返回NULL.
( E; Y2 N, z8 k2 ^
" q9 d9 X0 a3 S& o; R$ x5 a8 ?; Hvoid small_free(void*mem); 释放内存块.0 x ?5 J' t: L* `0 j
4 _2 }) t% o. v( t$ l- [5 S
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/ O0 j& L( M V/ k8 j- |8 V<<SmallMmem.c >>
! f! Y( q9 D2 j4 X( n5 P
; K: ?/ \/ b$ ?: c1 @/***************************************************************************************************
' C3 c8 w, N+ m Small Memory Managment ....
! _4 B2 a4 Z: H8 G* P Copyright 2008 by David Xie
9 G2 }* ?3 F" i4 D9 p$ g, e# d" z" T$ V
Last Change: 2008-10-10* f% b' A" P: _- v
9 j" d% ]+ }& E ListHead Byte: Bit7 = 1 Free Block7 b& d$ l* Z6 b5 S% h; M
Bit7 = 0 Used Block
5 ]6 o( f% A: F! ]9 b7 B0 k0 L' E( [# Z" [, j# |& c6 Q
Bit[6..0] = 1 - 127 number of bytes of memory block
; |" c' [ S$ W! S" c7 K Bit[6..0] = 0 end of memory block
; }3 a& H( X: C/ ?" ^7 l% o# f% a******************************************************************************************************/ J9 k; q+ Q t% A. ]1 ]+ Q
6 M1 V3 b5 d6 H+ G$ H$ c#define SMALL_MEM_SIZE 1024 // 依你的系统来定.# p P* h8 W! o
#define SMALL_MEM __xdata // XRAM( b- E6 |1 G' V' N2 {% _
7 C$ O9 o" s* t+ K4 o2 U/ f4 G- d//#define SMALL_MEM_SIZE 256
; t; f( [8 f U. }! s3 X/ k//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
2 `( U9 a6 _2 L' L: c
& O8 w# [. d" xSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
! S& f! s5 `8 }* R/ ~9 @
( L/ g8 ^5 t) Y: t: [, Uvoid small_init()1 V2 m4 E2 p+ B$ z
{
" o- V) J9 P- o unsigned int i, n, len;; E: _% u9 Y$ g8 o) s& v
i = 0;
9 w, y. X+ _: X5 @/ g n = SMALL_MEM_SIZE;
9 k* `% [8 F; A& x+ i3 G% B
" A* X8 I4 }) |% S( d if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
; P( _0 m; z, Q2 ?: q SmallMemory[0] = 0x01;! a9 J' K- o4 M) r. \7 f4 {' b
i += 2;
% W: s1 i: y1 H v4 o& Z# ~ n -= 2;, Q# y* r5 a' y% D" I4 Y
}/ T5 I0 }* o+ l6 L
. K& n, ]/ \$ U2 _. g
% z# z) T6 ?. a- o' m3 g5 m2 K9 o
while(n>1){ /* Init Empty Small List */
& r. A' |+ i: n9 W- c3 v len = (128 < n)? 127 : n-2;& v1 H& I9 G) z5 |9 D Q/ o. h
SmallMemory[ i ] = 0x80 | len;! K* p! f4 k9 ^. x5 g
len++;# u+ b2 {6 Y/ Y
i += len;- ~0 y. T6 q4 \! x; d
n -= len;" q9 a8 Z$ G8 l1 e/ c
}
& f9 i; m/ f0 H! q. q8 b* t SmallMemory[ i ] = 0x80; /* End Of Small List */# w! S) e7 D% n( n+ R% y( S& B
}4 l" C' W2 e2 \9 k9 o* v$ W
; H4 `: ~8 R/ @void * small_alloc(unsigned char size)- f- c5 E! T7 q8 `, b4 F
{9 e% Y4 J/ b) A4 v' Z
register SMALL_MEM unsigned char *p1, *p2; x" ?: c- w) m- d+ a
register unsigned char len;5 A+ [& {% U* h9 i
0 B5 E: e. H- ]3 d5 r3 X if( size > 127 || size == 0) return NULL;: v0 f3 d2 t6 p
2 x( X w& g2 L+ B: Q! X6 d6 [
p1 = SmallMemory;; i' A, c9 H" y" V4 U
while( *p1 != 0x80 ){; s6 i6 b; ?# U9 ] ^- v5 U
len = *p1 & 0x7f;1 a2 t* J' B9 M. ~1 z a" T5 P
if( *p1 & 0x80 ){ /* 找到空的内存块 */# a4 S) U$ Z+ e
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
- Z* Y/ A- f" ~0 y7 b p2 = p1+len+1; 1 X# u0 z8 x( j/ R' B9 d. R
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */9 I v( F8 a( W! X! u. V* N# x; I) S
len += (*p2 & 0x7f) + 1;
+ q1 h$ Z [4 d6 v# S: y& Y0 } }else{
; e7 G1 i' Y$ }+ D2 F4 |! w, ]" O9 T break;
/ ~0 c* O% W1 S) E$ R, P/ N5 J }
4 ]% ]4 e8 C% u8 {5 H7 f }. p( X* n) z1 L( y0 {6 I
if( len >= size ){ /* 找到一个足够的内存块 */
; _0 V0 [ c2 b; ~( N if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */% v+ m1 U% u6 y! `
*p1 = size;
) Y( P# n3 q$ V p2 = p1+size+1;. V7 Q+ Q" j; U6 Z; ]
*p2 = (len-size-1) | 0x80;( X# X# }& ?0 O9 |8 |: Z
return p1+1;" X: g* l. K6 b% l$ r4 t
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */) }0 _& d/ Q6 W5 W2 O6 Z4 G
*p1 = len;
! t1 A; g; g1 |2 P return p1+1;
O5 K$ g8 O' i2 d$ S5 Z# t0 G }
: M5 f. H/ O% v4 S }
" t% Y4 O* x( a }* _8 ?8 h# A, G
p1 += len+1; /* 找下一内存块 */3 w9 W2 v! _1 t2 V S
}( T. `1 e# q: v3 Y" }$ ?) @5 s; P
return NULL; /* 没有可用的, 返回 NULL */
2 w+ D- M! n) ^7 `& Z3 w}" L6 f8 Z! |( H9 g
0 ]' K3 H% K) n
void small_free(void *mem)
2 R4 H9 w" k) ]% ?7 P1 b{
9 c! t' E! [% S) |7 D& m" @7 Y2 O *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */! v, U! _% H9 y0 F1 H! g5 c
}
! g V( O2 J6 u; r4 d& R; i, B# u. u
|
|