|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
# Z! @1 i$ T* h3 `因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.$ `2 h* ]( } G4 b8 s
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:/ o- C5 T! W* Q8 K+ g
0 ~3 `& l# h s8 A
" I9 @( U( R& B$ L2 n
仅三个函数:
. u3 |5 u+ @" E k/ O3 Z8 B( O3 E1 E# R% i/ {3 n2 J
<<SmallMem.h>>) L, W0 B) F% ?0 j
/ W" s; _( a" t+ C% W6 C" avoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.# [5 s" q( D: R$ f
4 t g5 v$ k; I& O2 ?1 B
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求." v/ F/ R5 \" H) m1 [# Y
分配成功则返回地址,否则返回NULL. + i" l6 Y5 X+ J- |- `9 `( k" A
C& s! ~3 H8 [void small_free(void*mem); 释放内存块.
; R, e+ N% ~5 ?3 I1 @" u& ~% O; ^
& I( E+ i( k8 V2 q4 K2 P! c0 p-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------1 l& F8 r1 R' o' @0 X+ H
<<SmallMmem.c >>. p& `/ b3 K$ G! B5 z# S
1 o5 _2 d& F' o& ?
/***************************************************************************************************
1 E, v* J, b. F ` Small Memory Managment ....* @6 ]# Y( W6 ~& D$ F0 K4 Z
Copyright 2008 by David Xie 6 X8 U( E' ?8 l: {& H' m
! ~7 m8 B0 b0 f: [3 d
Last Change: 2008-10-10
$ [1 a% @/ v- l' v9 ^5 v
+ j6 D" P8 k( a2 I6 l* v: y7 R& W ListHead Byte: Bit7 = 1 Free Block6 L# z) T. E$ b0 O. D
Bit7 = 0 Used Block
* |' d$ ~; v3 y. M9 u; g) u1 J' z, z* V, A2 h. K
Bit[6..0] = 1 - 127 number of bytes of memory block) W0 D+ u' s) g5 A7 L8 c! o1 j
Bit[6..0] = 0 end of memory block
8 u, s0 ^# @, T/ e( n******************************************************************************************************// }4 p$ `" B! x% q0 v$ J! \
, n. I- {4 u8 J e! P/ [6 I' e) H
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
2 G" o) y; n t% B1 L9 b, n$ O#define SMALL_MEM __xdata // XRAM% K+ _/ k! \. h% Q# v3 S
9 I/ g: |" P3 v/ j. @+ }
//#define SMALL_MEM_SIZE 2569 ?1 N- l" P5 E: N( }0 G
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用./ Q1 _: d) w e6 E+ ~& d d1 I( L7 n
* B, W! R: ~, F ~; G
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
; R$ w* F! P% `4 s4 A5 A9 F( P
5 C \% Z; Z) n% I" Jvoid small_init()* J/ @& f" Y) A, X( e9 i+ B
{( S# \; p! W1 S) T& x( @) ~
unsigned int i, n, len;! V8 ?/ l" @* ?6 l
i = 0;9 B" G# S% d" d9 w$ J
n = SMALL_MEM_SIZE;- _8 {+ J( W. \ R
, h7 h: U* Q8 @) p z" R! z
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL *// w/ a0 X0 l: t D
SmallMemory[0] = 0x01;
( l: s8 a) q3 ^3 H6 C. _ i += 2;, ~! o' d* E! n2 w& r3 `, f, u9 l
n -= 2;3 q, ^* n" o# r% {/ U4 E
}2 v- K! c1 n. E
3 l6 y( L* a5 L1 i
O5 [6 E( F7 S+ J) C$ u" C! R9 X$ p& V while(n>1){ /* Init Empty Small List */, X, D6 l/ X# d+ Y4 K6 c* w
len = (128 < n)? 127 : n-2;0 M b9 V; X& \5 q% J5 y0 u
SmallMemory[ i ] = 0x80 | len;4 t8 b/ ]; M0 R& J- W
len++;
- G, X; f3 E K ^2 y1 S i += len;
; g) R, j3 E# i) H; G n -= len;
9 \7 h+ F+ o- K* N& G6 W, u y }2 r- R |3 e9 J8 y
SmallMemory[ i ] = 0x80; /* End Of Small List */. x4 }" o9 i) c: Y, m5 [1 o
}% r2 W5 w7 a6 C: b! Y9 v
" ?. ^$ B. Y6 K6 d5 [
void * small_alloc(unsigned char size)
9 b) w5 q% o! i3 Z( Y- s: i1 V) n2 K{
) d! o4 H% c" q! j- K4 @ register SMALL_MEM unsigned char *p1, *p2;
. T N+ U' t, Q! d- V register unsigned char len;) k% p3 E0 @- O7 O3 u8 A+ E: B
1 g$ g9 M# p$ V6 b
if( size > 127 || size == 0) return NULL;
* ]/ q9 W: S4 I. L. }$ D8 a. P% E) D9 ^( A9 N( \& T+ k9 Y
p1 = SmallMemory;
1 T( H4 \1 n. {* i' P: X' S while( *p1 != 0x80 ){
2 `6 m$ }" ?0 p% H! H len = *p1 & 0x7f;8 P6 H! m# a0 C* q- f( K
if( *p1 & 0x80 ){ /* 找到空的内存块 */
3 J: g8 n& R5 z8 D6 @( F! @% X while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
- z# S) o5 u* u5 d0 F p2 = p1+len+1; 7 u; |2 _( H$ V
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
! c4 `. Z: A x# w x* I len += (*p2 & 0x7f) + 1;7 g) Z4 ], ]0 L6 h" H+ T/ `
}else{3 N$ w- x1 D8 k8 p6 Q3 [+ ~( ^
break;: c% v' J& L6 t& ?5 }
}& h- |( L. t1 @" w9 W2 b( {0 y
} Y) y8 a9 n% Z6 r* ^9 g8 T
if( len >= size ){ /* 找到一个足够的内存块 */
2 n7 y- ~; y0 x, d. l if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
1 e P& |* b; h2 h. y: `- R6 F8 e *p1 = size;
* o; b6 p% ~1 j* H: j. G; [ p2 = p1+size+1;: ^' l0 j3 c; x4 Z3 n$ x0 L6 y3 r1 E
*p2 = (len-size-1) | 0x80;
) U \) {* {( ^4 c return p1+1;4 C2 ]0 i Z1 G0 z7 @
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
. Z7 G) [) h* l# i I *p1 = len;
/ @" _' T- x9 K% D return p1+1;
* i9 y& r5 b) D: u4 [5 R6 c! l" x# I }
# H' \! f1 @' a0 d/ l9 v) B }) I) l2 W0 u8 T2 N
}- }" h! K2 P, k; b
p1 += len+1; /* 找下一内存块 */
4 R s5 O' K, X4 h }
6 K$ b% V. c3 R$ j" J4 O return NULL; /* 没有可用的, 返回 NULL *// J0 A( f4 o1 @7 k3 H" ?6 C3 U
}
0 h; [4 l L4 {2 s# z+ e7 n
% V1 w+ G' f1 ?+ Z, r- Z8 \void small_free(void *mem)7 C! u9 C9 a i3 _
{) D1 a) S4 V/ @ \% e |) b
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
' N- O/ t: G" E1 i3 B}
2 S0 h2 ^$ I- s' \9 b: F5 |, q$ ?% \7 l/ e& q, p H# o8 }
|
|