|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).# W* u) Q* r2 c2 X6 r1 u
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.1 F, l) m2 S- M( d
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:* Y$ t; U7 n) k; m
! W' k- ?* f. X& H) `$ K- U" D7 n& |
; L4 O! n' \* Z7 }% C" [1 l4 H仅三个函数:# H @" V9 s7 ~2 f' d9 k3 [
7 {7 W3 v3 m$ M+ ~; b
<<SmallMem.h>>& S$ L' f9 W) N0 e3 m& L1 r
, D" P }8 s: @void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.& z* h! x8 r' M0 F7 G3 ~
: P8 ?( w2 A0 L5 T
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
0 `) m* ~0 J% T 分配成功则返回地址,否则返回NULL.
- ^3 d3 V8 o8 b: w6 X% R2 p
' ~3 B3 K4 x z) tvoid small_free(void*mem); 释放内存块.
* E# @" x8 ~/ v# G6 X4 m( g) L7 i
Z, {2 T+ d _& ?8 v-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0 t9 U1 ?6 k5 G9 l M. p6 D: o# \, D D<<SmallMmem.c >>
- N4 a9 p. p: x! U0 o
, J# V4 f" j7 j/***************************************************************************************************
$ R7 S4 U2 w& r# V Small Memory Managment ....
; n0 Y+ B+ O5 c8 V Copyright 2008 by David Xie ! R% q4 i9 }: U' X& g) k5 ^
! h8 z, U- Q1 p8 r$ f6 e, ?, M$ ^/ M Last Change: 2008-10-10" ?) H# l3 r5 \/ y& }. Y- w! B2 ]
/ `9 u, ~' n& j$ q ListHead Byte: Bit7 = 1 Free Block
# \4 {; A6 M2 D+ z+ m Bit7 = 0 Used Block
8 _) J9 p& v2 q$ T+ Q# N1 |/ j4 ^8 C' `6 V0 |) N9 L
Bit[6..0] = 1 - 127 number of bytes of memory block
+ T: I1 R- _( q/ b3 x7 w! {" Q Bit[6..0] = 0 end of memory block
* p. q% V) k9 j) y+ b R******************************************************************************************************/
$ O" x1 k9 \7 W6 T: i% Q6 G I
# I2 f) l$ O- e9 ~- P#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
! R: L/ z3 D: Q#define SMALL_MEM __xdata // XRAM
( F3 v2 m0 v* E0 ^$ W2 j7 ^$ C# P# c5 j v
//#define SMALL_MEM_SIZE 256: ^4 ~' R$ [, H
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.1 d! q8 E/ Q" w1 c& t8 `
O& E% M+ b6 H6 i# f) |4 z0 XSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
- u0 ^* |1 M z
) `5 k: s, r' f# b) a& ?void small_init()4 U$ z4 e: l7 u4 `4 X* W* B3 f5 k. {
{
% q, v. ], A. w/ [ unsigned int i, n, len;9 \* j! e( U# ?8 O3 [( S" z
i = 0;, {/ S3 W; S& H- V6 |0 H
n = SMALL_MEM_SIZE;0 h% Q! o1 W4 k, j9 [
. h1 q. z5 U" a" w6 D& x7 K- i0 O, T if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */$ Z* | A Z6 y
SmallMemory[0] = 0x01;
3 n& j3 O! m- w2 t6 [1 P9 |4 ?3 ^ i += 2;
& x0 j/ G) Z p) `, D; @+ T n -= 2;2 L- E% Z5 b7 i6 ~, m5 ], o4 p4 J
}
& c+ ?& J' U# \( ?/ Y
) ?# N$ | _* o/ O: E1 t0 e6 b/ C4 C& p& w P
while(n>1){ /* Init Empty Small List */
" \+ M' p' t# X. k1 ?+ p2 l( C len = (128 < n)? 127 : n-2;
5 z5 N0 o+ I* z% k! g# U+ f3 ^& k0 ` SmallMemory[ i ] = 0x80 | len;
; e, Q3 `7 d3 h0 r5 _1 N3 V* \# | len++;
4 I9 _" @+ m3 O1 ~5 i! U+ K5 s i += len;
3 M* f7 ?7 A; ~: d n -= len;; Y! j/ S: R" j% Z5 t
}% |5 u# s7 h& x
SmallMemory[ i ] = 0x80; /* End Of Small List */5 k d* V: Z! I' f" h% O O
} P5 g3 ~( k) q) n/ Q* k
8 O g6 {0 m# X0 g9 L, j, U: Z# ^
void * small_alloc(unsigned char size)
2 ?, |+ g, G3 ~6 d: V! m5 y' H{
" Z1 s# P7 {# K; K register SMALL_MEM unsigned char *p1, *p2;
! p1 H( j* K: a' \" p register unsigned char len;8 ]& T6 \- D3 ?( g+ P/ g. Y- W
0 ]2 h1 W; \) p6 l" _& n. e0 X if( size > 127 || size == 0) return NULL;# a% u0 v5 {/ |9 m# G
' F8 e) w! b$ S) z# ]
p1 = SmallMemory;
4 v. V$ A* G' I g) j while( *p1 != 0x80 ){
( p ^! l) t5 O7 H7 g5 { len = *p1 & 0x7f;
2 w& y6 j& R/ r" b- C if( *p1 & 0x80 ){ /* 找到空的内存块 */4 Q q# y0 R2 M3 B7 g3 l) y9 f+ l
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */6 j" W: I$ f3 H5 h# _
p2 = p1+len+1;
* q9 Y2 h0 m- I# |6 A$ d3 F5 a$ u1 T if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
& ^1 g0 t# E/ U8 p len += (*p2 & 0x7f) + 1;
% {4 ~ `0 D& z; |4 D) w }else{
6 b' v9 z( ^# E6 Y" C4 P! T break;4 {) Z! E' R7 a( M% n$ M2 L
}
+ A7 Y1 P( G W: z' f }$ K7 o4 ~+ G3 X$ T
if( len >= size ){ /* 找到一个足够的内存块 */+ k# _: Y8 I% ?7 K4 r5 d( E
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
2 v. }) z- f& t1 o+ r *p1 = size;
$ i! {% q4 j- J0 Y5 O1 ^# }9 E5 n p2 = p1+size+1;
# u/ s, R, _ J$ i *p2 = (len-size-1) | 0x80;3 M* [3 ^2 x Z3 w- s; r
return p1+1;6 Q) E/ Q, u, @& C* m0 `
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */0 l/ O7 \. m* P& b* G
*p1 = len;9 e% Q% @' o$ J- l6 L' T
return p1+1;+ f% `. r3 |3 i3 J4 i) t1 ?& L/ U
}
! M5 n. S6 P/ A* n, p }0 [3 M b, ? V# F! M( Q
}6 b2 k) K- I& |; o# O
p1 += len+1; /* 找下一内存块 */
. t; i% E/ F$ r$ u' H } A5 M( e+ q: T9 H2 V
return NULL; /* 没有可用的, 返回 NULL */
* F: R8 m* w# t/ K' z/ `: f}* @: {7 M1 |) \) D: A6 b
- |' Y3 v8 B5 V5 n" j& Y2 F
void small_free(void *mem)3 n/ W' d2 ?! X9 z& ]: C
{; y1 ]% T' J! l& B/ h
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */- [. ]8 N3 t' O; s6 W
}
- `# F2 j# M' X5 ]6 E+ |$ o/ U
( W% y% n4 e& ?8 s# ^3 _3 Q |
|