|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).( ^& \0 E; }; s6 Z; [0 S/ P+ u
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.' \: Y# s4 M1 ]7 O, m5 g
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
( X& z R w" U& X3 n) T- U( W( C; f( b! V d" j
* a6 j' r; K. K% ]1 m
仅三个函数:% ^ [2 f1 @6 G0 v- i4 c, Q# U
; B9 [& a, ?7 d( Y
<<SmallMem.h>>
: }) |; |( i4 H: q" d2 w; D' \5 O# Z
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
. U( n6 X- r& a* K; q& J
; O8 B8 f' W, Q! Wvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.& P2 R- H, M. G/ i
分配成功则返回地址,否则返回NULL. & m+ A; \' i% s& F, M. P
3 Q4 a3 ~9 N! P- Q, z& q
void small_free(void*mem); 释放内存块.: J% ~8 l) Z7 t- T
5 E8 P; w' T6 k6 Z' n0 [" O; B, X- Q-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------( \6 @6 W4 {! n# W1 o7 s
<<SmallMmem.c >>5 n3 X: a3 W' G6 V
1 [0 y3 D$ {. d% ]7 D4 y
/***************************************************************************************************
4 y% z4 i% S0 X" ? Small Memory Managment ....! j* W2 O' S" [2 [. O+ r
Copyright 2008 by David Xie
3 g6 W; H$ E" @: ~+ Z M9 F& W4 w; X4 `. I/ S$ g# X3 ]7 A
Last Change: 2008-10-10
) f0 c0 Q3 k3 Q. v
0 c4 h% u( q9 r9 ~8 q+ D% j8 { ListHead Byte: Bit7 = 1 Free Block
# B7 r3 d# o6 W3 R- \) V8 z3 q Bit7 = 0 Used Block i4 y( |9 \" T) h* N3 q. W- \
3 X# F) S. x! @6 K2 m5 S9 P Bit[6..0] = 1 - 127 number of bytes of memory block
# b9 L" A2 h& ]4 g) a `2 E Bit[6..0] = 0 end of memory block7 b N2 P; Y- J- y2 Y) Z
******************************************************************************************************/
* @$ R# G1 }( F; ]) e3 A
; ~9 D- i2 M, N/ K3 o5 P( {& T2 M* J#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
( h. t/ j4 h+ |. }#define SMALL_MEM __xdata // XRAM; f0 W C8 f1 D5 \3 c
. q" w# [& @0 ?( ^/ C
//#define SMALL_MEM_SIZE 256
& P2 B. m- K6 l& f4 P+ k' p0 Y//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
9 J6 b1 S8 m! _' P! P' T
9 Q1 Z; {. K I/ l+ n7 {! G5 TSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
! X' _+ M0 E: t" H, {& r+ A
( j& V0 r/ W# Q0 F" Hvoid small_init()7 X. H" ]4 G6 Z# }7 w6 R! k
{$ M9 U. T0 k/ g3 A9 E* o* t* v0 z) d
unsigned int i, n, len;
. d% s. ]$ `4 l0 s: U' d i = 0;1 Y' d( M3 l5 J
n = SMALL_MEM_SIZE;% l* s8 Y; @8 Q$ z3 ?; a4 F
% U* r) l8 h. O, j5 l
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
$ y7 r5 F- g# l0 F/ l SmallMemory[0] = 0x01;$ F+ e# c; C; X' U# U1 C
i += 2;7 F$ ] c+ Y0 `6 _# g& C
n -= 2;1 T1 r+ X- I9 `$ `8 }0 f0 Y
}8 D! W' Z3 `; `' }
2 v5 L- U7 h. s, a
" I, Y8 Y' r. e7 \5 U while(n>1){ /* Init Empty Small List */* F1 }" ?" t, ^ M7 l- U0 B
len = (128 < n)? 127 : n-2;
& C; q. j+ m/ [) R8 E# k SmallMemory[ i ] = 0x80 | len;
& Z. U/ P1 ^" I# z% y: Q len++;
, @$ Z$ L7 F; L/ q3 D8 O, K i += len;
' E: q5 S- G+ F n -= len;
2 ]7 E, L9 \0 e$ `. l6 Y% a" s }
6 F6 e- K9 N0 }, q; e' L1 y6 j SmallMemory[ i ] = 0x80; /* End Of Small List */7 d* \4 ^! _" @
}
2 i7 r; ~6 |: ~- t: V" r1 ?: `- E. O* c4 n: p# [4 f
void * small_alloc(unsigned char size)
/ R& M0 ?0 C( W+ V. d{* @! @, t$ b! f5 E( P
register SMALL_MEM unsigned char *p1, *p2;$ U! ]/ _% Y; f- B4 r
register unsigned char len;2 E) [5 t. r8 z/ }2 s6 y* h
0 ^ I: `2 j6 O* D: H4 s# A. q
if( size > 127 || size == 0) return NULL;
% i( `7 }$ s& W+ X4 d2 Q
+ W! H3 g2 p9 z p p1 = SmallMemory;0 ?4 H1 m6 ?# `8 M
while( *p1 != 0x80 ){1 {, n/ l* g' b0 l6 m9 k
len = *p1 & 0x7f;% u' h2 K$ p% @+ k) j: x' \4 p
if( *p1 & 0x80 ){ /* 找到空的内存块 */
3 ~4 U. d& ~, m& t, D while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */0 b5 _7 h* s4 |" l2 f
p2 = p1+len+1;
5 A( k8 g0 u* N7 O) @ if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
; g" b, N. K8 ?5 J len += (*p2 & 0x7f) + 1;
6 o5 _ f. @& D# J: l }else{
2 t7 ~$ |# b# S3 I break;
f3 O s6 C; \! Z: F4 } }+ q, ~9 s$ h) b$ Z, ^
}
# a. J$ P- C8 I8 u/ t if( len >= size ){ /* 找到一个足够的内存块 */( d$ s& J1 e& L& e& f; h
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
+ O7 I7 a. [8 m7 B p, \ *p1 = size;5 U1 |9 l5 |6 ^( O9 l5 e6 W3 C
p2 = p1+size+1;
* O) b) j7 o- P+ p) U% Q *p2 = (len-size-1) | 0x80;
- h: ?# }- ?: W return p1+1;
! _4 g5 }3 A& b4 Q& I1 j) O$ W }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
1 ]5 |7 x2 B: U4 ]& y: Q1 J *p1 = len;
$ {- M# U% W4 O& H return p1+1;
3 ^( h8 V G% B9 V; m }! Y$ F! n. v" v o
}
( a! B* d+ ^7 x% [$ [ }/ m2 A9 S; G# ]2 O, y2 {$ Z6 t0 C
p1 += len+1; /* 找下一内存块 */) |8 O& c4 O& ^; j2 ] P) S! \
}
% f3 n' z+ J0 [: ^- ] return NULL; /* 没有可用的, 返回 NULL */7 E, q- C F3 @$ ~! ]
}
# r5 g- o* t* N
$ E9 X7 C6 r9 M! z# T0 mvoid small_free(void *mem)8 T9 v0 D# j! a
{, Y) h& @6 {* {7 F- u+ t
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */% Z, C0 G" l' _1 U
}
0 h$ V- E8 \3 ~) c1 C5 i0 u) H ~7 p
|
|