|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).5 m" t4 b; P& b6 g# I
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
. h" W" T& @. a正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享: C1 M6 P2 ^7 x( p/ }' L+ e* q
6 f! L/ w% E: u; _/ @- T7 x r
) A5 t! s" H. Z/ \, G1 h/ Y9 N$ ~6 f
仅三个函数:/ n4 S8 {9 D- _; K3 Z: b
3 U. J8 d& e l7 g+ I4 g4 U
<<SmallMem.h>>
6 s% Z, C0 {4 X/ S* ` s% _
$ C2 ~& X- K* evoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块./ e: o/ {2 M* w! \9 h) ]
) T5 I- ~; A7 Q D. {
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.: Q+ w, g6 M' g2 X4 u$ {
分配成功则返回地址,否则返回NULL.
M- V# ^' C H0 c, m& p4 m
; x. V$ H/ n' T' S. @& o2 A& rvoid small_free(void*mem); 释放内存块.
& W& t( C' y9 H4 z4 W3 F* U
5 i. H9 e+ S( Q; T! s/ }' ~-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
7 @* N4 ]/ i% c( W/ C$ F0 d) _# I<<SmallMmem.c >>
# \& X; j7 `# L* M3 T P/ v8 c# o7 t+ w
/**************************************************************************************************** n& f5 ^, j4 i8 q. E
Small Memory Managment ....
5 P( ^" D* ]! J( E Copyright 2008 by David Xie
( V+ ?5 e4 ]4 v' f6 j/ y& q8 J! w1 p; S* c
Last Change: 2008-10-109 W4 d3 @( }9 v! ~
) N/ Z, `. E- O6 V' z# n ListHead Byte: Bit7 = 1 Free Block
) g5 I. k' d; ?' x! v Bit7 = 0 Used Block
[' o; O! m8 T% o' J
7 d" A7 R# V" L0 _ Bit[6..0] = 1 - 127 number of bytes of memory block0 X, v% C3 n4 }2 { O1 l
Bit[6..0] = 0 end of memory block
- Z& Y* s E6 P8 X8 w6 x******************************************************************************************************/7 S3 ], z5 T/ x) K, U5 O
% q( n0 o: }- h2 ]$ L/ N
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
; Q) J2 ]% @# M5 S3 ^' |#define SMALL_MEM __xdata // XRAM& B1 N8 d! s4 E* ?4 R' M! V$ V* \, u
4 e+ s5 ?, J+ k9 J- n: \; `
//#define SMALL_MEM_SIZE 256
& } C: |7 J- h5 b0 u//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.- R" F( O+ E3 B; ?2 q* s
) _+ T% ~) A( N2 w/ x
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
9 F# j4 V2 l2 R% V1 T* g7 g! ?7 C+ S
4 w9 j! w6 Q$ Zvoid small_init()5 S1 \$ X9 W4 i9 ~
{
+ k1 b+ N& @2 v) M( P" |4 V unsigned int i, n, len;
! e9 {2 p Z& u$ v# ~8 j( k i = 0;0 Q* ]4 o) c! t/ y' `9 H
n = SMALL_MEM_SIZE;
# S- X, R( j2 D- l0 M, l. z+ w6 U' ^- r+ |9 f' q
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
7 r/ B8 ], Z Z, h( {, j SmallMemory[0] = 0x01;6 n( a! ?1 m. P: F6 C: v! O+ R$ ?" R
i += 2;
1 p d4 s" F" O' Q Z n -= 2;/ i* A7 A% i7 k1 ]( V
}' W2 p8 k5 s4 c$ S
" U& q c" ] N; e
( t" e$ h! A. |* I* C _ while(n>1){ /* Init Empty Small List */
% G1 a6 ]7 s5 ` len = (128 < n)? 127 : n-2;
$ j' y" s, H1 O8 A1 m SmallMemory[ i ] = 0x80 | len;
' J5 K% L5 M' _3 z; [1 ? len++;( p+ ^$ y# Q$ x, P8 D- f
i += len;# o2 a8 c: y6 |4 U3 R; k$ p/ W6 S
n -= len;2 d' [0 K+ r2 j& P" G
}
% ^% W: w, s6 n- T1 r( o% M( i: F SmallMemory[ i ] = 0x80; /* End Of Small List */6 O+ C% \8 C6 e9 {
}
U& z1 z% [4 @* I) l6 T
" c" I; h$ w: c0 t3 ~: J" `void * small_alloc(unsigned char size)
$ K* ?; j: `# Z{# }" j$ v3 x6 \# P) U N. P
register SMALL_MEM unsigned char *p1, *p2;
0 ^- m( Z& z/ V# }- [ register unsigned char len;
V! O" ?) N: l. D5 |
: G% J) s* ~9 ^ C if( size > 127 || size == 0) return NULL;7 h O- r0 A" b4 F6 D
$ r9 T$ }' n/ y5 t3 Y p1 = SmallMemory;+ Q. m# U! h; L% m" X
while( *p1 != 0x80 ){
7 y7 f0 @8 J9 C; J len = *p1 & 0x7f;% e' n1 G3 _8 f9 K4 i2 b
if( *p1 & 0x80 ){ /* 找到空的内存块 */8 ]" y' T# ]. }% _$ T( `
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */8 n1 V. N( H) z0 G
p2 = p1+len+1;
/ x# s" t; \ C9 c if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */( B1 _9 N: N( C- b+ D n
len += (*p2 & 0x7f) + 1;
" }, N0 _, H4 j1 U }else{
9 N: `0 r: L; r6 r" ]1 p# C break;: T( Q5 O5 h0 K6 ~! P! E) c8 v
}
% g; r; o) S3 a! S0 H }
3 M, o6 X' g9 |) q- i) R" t if( len >= size ){ /* 找到一个足够的内存块 */ O, j* u- U O5 b
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */. O& h! z9 c! j
*p1 = size;! v; d% L) w9 \1 ~6 F4 P' O4 R: E
p2 = p1+size+1;& o; Q2 U+ I" {
*p2 = (len-size-1) | 0x80;
' k. ]' e! o; F. F4 i( K return p1+1;( z5 ]1 P- u1 u, l
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
0 X, f: I* V# Y8 g *p1 = len;
) r) f9 ^9 `, k0 N/ M return p1+1;$ ?, K4 ]4 Z$ M6 {. F1 d
}
; U3 g- U- F( V0 {6 R }6 a- a+ Z& s# C* e; B: T+ Y) M
}
3 ], s2 ^3 f) v5 q) z; X. w p1 += len+1; /* 找下一内存块 */! [/ z8 Z2 V* h9 X
}$ q. P; k& Y6 h
return NULL; /* 没有可用的, 返回 NULL */8 o. ?8 ~' x8 V6 q2 T: U
}
3 |, F! N( N9 X$ A, j0 O
& Z( f* U1 A; b4 \void small_free(void *mem)& i2 S+ W0 _4 r2 G' o0 Q3 |
{
" B: G7 ~# f1 I+ d. X; y) x g ^" B *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
6 G* ]3 w3 g K}4 k/ B+ z( R5 ~. `5 e1 z
: D" }5 v$ ^& U- q! m& T! C( p
|
|