|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).( e' u4 {! w& ^% z
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.' \. a4 _6 B' W
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
, Z4 l2 L. V& v6 h0 L7 P0 K% E8 c2 b0 Y, u: ~0 K7 k. n4 d3 R- \
* S% Y+ ]1 d9 @4 q4 O
仅三个函数:
5 _# ], F7 B0 ?) ^( F7 b$ E& K8 R! A1 q( V1 C9 i, p& l( b& a
<<SmallMem.h>>* a; i# R4 D2 p8 [ J" ]9 H
6 D0 `# q" h& G
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.9 \1 ~/ f/ a+ p$ ]6 W! N& z( F7 [3 P
) w8 J$ U( [9 D+ Z' N( `void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.% |; o$ @) Y- k$ L' H! }
分配成功则返回地址,否则返回NULL. ; w! @; v; {# ?" Q8 b% G6 }' K
8 e2 O) i' n- \, Q. ]; i# u1 J
void small_free(void*mem); 释放内存块.
/ c6 y+ U. p7 H. ]& H
4 I1 A" \9 L R P' ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------. e% I- U! `! a& `! ~# q/ j9 Y
<<SmallMmem.c >>% U$ C. N$ ?1 r0 E9 Y: X- F
+ S+ U. a$ q) R% ^
/***************************************************************************************************
# Y t& B; M1 n Small Memory Managment ...." j. \0 [; C4 J& G5 @
Copyright 2008 by David Xie
7 X4 o% Y; k0 f9 V( Y% N* ?$ ^3 \
Last Change: 2008-10-10
/ h- `! j* E( w( U% m
# b8 _' v# W3 O; K% g ListHead Byte: Bit7 = 1 Free Block( s& B1 m; f! L/ g& `& U3 k
Bit7 = 0 Used Block& L2 @" R; W. ?1 j! f
; Z4 ~6 k$ r- \( l; ?* f4 S8 g- z5 ~ Bit[6..0] = 1 - 127 number of bytes of memory block( g) Q/ J W/ m
Bit[6..0] = 0 end of memory block! l% A8 M6 c6 k) f& G: J& q
******************************************************************************************************/
; M! G0 k5 @& C0 o+ m6 d) s- Q1 M8 K' l
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.9 |9 }% e8 {0 t2 [
#define SMALL_MEM __xdata // XRAM, Q3 f" L" G/ j7 p, i! v
* r% w8 y. ?5 c, \; }//#define SMALL_MEM_SIZE 256. {* C1 }+ k. b( U
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
) L" Y& i6 C1 Z" p! h( t7 [# S9 H+ M
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];. q" Z( v8 t7 U7 p$ L4 I1 y
# O7 Q1 l0 f0 j3 g
void small_init()( h+ N# r; V5 b& T P2 c2 E {
{9 l: I; B; q2 v
unsigned int i, n, len;! L( q5 G6 [: B3 I8 y5 B5 ^
i = 0;- u3 y# w+ b8 r! t/ P! m
n = SMALL_MEM_SIZE;8 @6 N$ d1 N6 U0 b1 x& I. n/ l/ A! V; B
5 [8 D! [! ]" ~+ _2 e
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
3 s# O1 ^4 I8 a$ k: V9 @# v SmallMemory[0] = 0x01;) j$ J1 k1 h5 x5 P3 M; Q2 |
i += 2;, u. S* ]' `; c; Y g! l" p
n -= 2;, K8 E# d3 d u! q1 F7 y9 r
}
5 g3 l4 T0 }1 {/ B8 ~* t1 V' h9 ^0 f; H$ S6 R% b
+ i; N2 T1 P+ f4 f
while(n>1){ /* Init Empty Small List */! b3 `: E" t5 `( h/ y+ [
len = (128 < n)? 127 : n-2;
, h' E- N. t1 X; @% O7 e- Y( |* e SmallMemory[ i ] = 0x80 | len;
# A0 X+ ?) k5 u* a' g; W len++;$ Z4 s) N: l6 \! A, k* ]" ?9 Z
i += len;) k" t) y2 {$ A/ b6 i2 v
n -= len;9 l b, l1 ^% n, U/ q% h
}
3 {, ]% w9 h* Q* Y- c SmallMemory[ i ] = 0x80; /* End Of Small List */0 l* `/ g# l8 H8 c9 I
}
# r' G0 B- ?. R) g7 l
1 r- a5 }+ ^, k) d0 Dvoid * small_alloc(unsigned char size); i, t, K M; [/ ^) I
{
% z5 x; ~: R4 E1 I% L+ u4 G register SMALL_MEM unsigned char *p1, *p2;; J+ U$ \, V- q% a$ ]
register unsigned char len;: u3 w& _1 Q" s6 f" f$ j4 n9 S8 x
* T0 k x+ |+ b3 V4 |3 n: g if( size > 127 || size == 0) return NULL;
* L3 w/ d. A0 y0 N* h3 M" ^1 c' n. ^9 u3 t5 j
p1 = SmallMemory;
8 W. @0 d7 m, t while( *p1 != 0x80 ){
! U: O% h+ b- b* y len = *p1 & 0x7f;9 J N) q% n; I$ u2 i5 o
if( *p1 & 0x80 ){ /* 找到空的内存块 */
5 \/ i- v! \1 u while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */$ w5 \7 |! G. g5 @
p2 = p1+len+1; $ z0 l4 k. D$ z7 @" U- G: `, i* v
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */' b" V3 k% \# z# U; ^3 R
len += (*p2 & 0x7f) + 1;$ T ?2 c0 _: A2 g* w6 l
}else{6 R) N" [$ i: Q$ j/ c
break;
/ ]% N; m" }! g }
1 S, ^& c* R, K4 N7 L }( c1 c2 d# R8 j4 W
if( len >= size ){ /* 找到一个足够的内存块 */' B' C! B G, \2 l
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */% v2 Z; k V R" o
*p1 = size;( H' |( P: J# z% k3 Y
p2 = p1+size+1;- J# _( i* E' l4 ?& N" {
*p2 = (len-size-1) | 0x80;- n/ p; l* ]/ F, u7 a
return p1+1;
1 ^7 H. s s; C d1 K5 ~' X! E& w }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */( o) O% }( O; c' W
*p1 = len;& T/ c) ^, p7 }% S; o! T' b# @
return p1+1;; |: L! @4 Y3 o8 d' @ e$ c/ ^! u
}
2 d& ?" p6 W8 O8 p* w$ s }
" f) I5 U4 D1 c& j0 ~+ g; T' _; K0 z }( ]- y, N! R: @
p1 += len+1; /* 找下一内存块 */
5 D$ ~+ s% R% m0 c- o9 Y }
* F$ t, d) G. n. ]) Q$ p" d" q9 P/ P return NULL; /* 没有可用的, 返回 NULL */
3 Y! O9 [9 w4 Q7 \# e}
& ^4 Y; c' Z. E. K6 t8 I) r5 j) [; V2 G
void small_free(void *mem)" w* w. d4 l0 Y, g/ o
{4 M7 w/ A3 p/ @ E9 ]# `" n
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */+ |( j% k$ j) t' O/ y- M( M
}
" `* ] W v7 K2 ?8 S4 J& k' m) h& q, Q( e. S) S6 K" H
|
|