|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
# S& P% \4 \8 \8 c9 |) o6 a+ x1 i5 V因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
; F/ K, d G/ R' j5 |6 u3 H正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:& L2 @, D0 [+ J0 h% d& ?
, r) ~. U$ m9 Z' v
. T, T; @' e. x7 k+ @
仅三个函数:! v' E4 \6 z' N, c9 P5 B+ d
; F, R- b% m; X2 D) b& `
<<SmallMem.h>>
; B9 b( b; g) y* a/ u9 Z, n% R2 ?5 _( l
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
- u' T C- R5 N" g% X& H* h& U" D' o) l
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.* s9 J$ b* z; F; o& ^4 g
分配成功则返回地址,否则返回NULL.
$ z" @8 k! a4 z" w* F: ~$ \ A0 v' s7 |* S1 ~" I V* L! ?
void small_free(void*mem); 释放内存块.! b% F0 J1 H) d! `/ }$ f& r0 a7 H1 Z
! T% k+ |/ Y R. c" g& Y- `0 n" y
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------4 q! O# q' L; ?( h& T8 y
<<SmallMmem.c >>
2 @0 f4 Y6 L( ]2 O6 D
! N9 A1 S$ g" `! t. R/***************************************************************************************************
+ A$ v2 i) |: o4 [ Small Memory Managment ....4 q1 G" p4 V* N0 y* O/ F, y# T, n
Copyright 2008 by David Xie
, E4 ?5 T7 w5 _, S" n4 C
2 M8 O: y4 I6 t+ n Last Change: 2008-10-10" t) @8 t0 ~# Q4 v# L: C& i
. h1 W* l8 T# Y: ?! G/ n9 B
ListHead Byte: Bit7 = 1 Free Block+ ^! n. e" n% l E% U
Bit7 = 0 Used Block, G: e/ X. d% k, l
4 X! l. ?" ?1 k+ i' ?1 { Bit[6..0] = 1 - 127 number of bytes of memory block$ U. K, i1 r8 i, @
Bit[6..0] = 0 end of memory block
. }' {( i: U0 J" Y9 s: Z& k******************************************************************************************************/
! i. I) Q7 [3 Y: q. G
$ K: S- E6 q6 f5 u#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
8 y) b9 t: s4 k/ T* P, `3 [; l#define SMALL_MEM __xdata // XRAM- m' w+ w$ C$ I0 y
% j# i: q! D8 T+ k6 j Q- f
//#define SMALL_MEM_SIZE 256$ O; |3 ~. G6 S+ d
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
: s# \9 O5 q# e8 G8 y
" Y3 z; R* v/ ?+ s- q7 e* i6 `SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];, e4 b: E R6 E& |8 F [
8 D4 r, O- h( c' A n; a- h- U% fvoid small_init()
3 @; ]' \' k3 A1 K* ~6 A2 w{
: t) n0 b5 s$ s& m% d: S unsigned int i, n, len;
+ k' r }2 i1 q0 i" V i = 0;
: \9 W* `: G. ^9 b+ O2 r' g n = SMALL_MEM_SIZE;( J8 g5 b6 p. t1 o6 d' H2 L
1 [" U0 O% T' ~ y+ Q+ p if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
1 `' J j& ~6 |9 r SmallMemory[0] = 0x01;
! [/ _9 i1 J: m; a9 | i += 2;: A- W$ G: I% Z( w
n -= 2;) W! G! m# A: K) k
}% G, U- X- Y+ x' B7 g* p
( M4 s3 ~) j z6 _2 n. C
" F/ T3 W6 u1 a( {
while(n>1){ /* Init Empty Small List */ m0 O* b$ C5 P: o# { t( H" N
len = (128 < n)? 127 : n-2;! D6 _6 F5 L" _5 V" [6 E
SmallMemory[ i ] = 0x80 | len; K Q& r7 i F; p1 h8 K9 N
len++; j, a1 I0 z0 f
i += len;9 e5 i3 k6 R2 o% H% c
n -= len;2 `6 a4 g4 Q1 }$ g4 x j! ?
}" V1 L* I- p6 |: u! p) _
SmallMemory[ i ] = 0x80; /* End Of Small List */
! V+ |* w! b9 }! D7 H9 ]+ c5 ?}4 C6 k" p) ^4 L) O3 u& H: m' \
6 }. C" i% g8 j1 w% ?
void * small_alloc(unsigned char size)
. I1 N b4 f$ I( g, J{& z1 h4 T- T7 B2 D$ ^0 v) f
register SMALL_MEM unsigned char *p1, *p2;
8 O3 T+ H1 x* C# e4 o' g register unsigned char len;
, Z- X' h: b2 w0 y9 r3 o. K
4 H# Q# R, R9 w( q6 O, } if( size > 127 || size == 0) return NULL;, r* H0 u' |% B1 B' D0 @! i! [
- ~9 _; \; x/ }1 O; Z p1 = SmallMemory;
- Y% g7 M1 d# T$ M1 z: V% Z8 ^ while( *p1 != 0x80 ){* p- `- F T6 h6 u6 f
len = *p1 & 0x7f;
* i5 U7 r5 F$ k/ C( T# {! x- j) m( d: @ if( *p1 & 0x80 ){ /* 找到空的内存块 */' W4 P+ L2 f8 p& E& Q% K6 a
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */8 \+ e4 F, b% o# S( ^: [% |$ `
p2 = p1+len+1; . L# l$ u" p7 E }' x" D, A, R
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 *// X% P4 ~/ ]% {0 ^7 m/ Q3 `" [
len += (*p2 & 0x7f) + 1;
. |" m# E$ ^/ M0 @* g( T4 T }else{
+ X" P$ E$ L1 j* C break;
' ^7 A% C+ x6 ? }
0 Y6 U! x0 q& F, H' c" { u }
8 i9 M3 u2 u( X5 V9 C if( len >= size ){ /* 找到一个足够的内存块 */* {+ d$ @5 u( r$ [* K$ Z) Q
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
2 h: J3 v0 N+ v% x *p1 = size;
% Y: C/ W& B/ ?2 S4 x p2 = p1+size+1;- c. _; l+ ~! A, @) N
*p2 = (len-size-1) | 0x80;3 @7 G3 N: ?5 K
return p1+1;" s5 C3 `' c: Q
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */4 c6 E( U( s" s V% f- Q
*p1 = len;2 w' b. t- I" ?- \5 z- V
return p1+1;
: r( F( \% Z1 s: s$ h& W# K$ B }
) x' Y+ P, a/ w7 [ }
+ g! f! l) W5 C }2 ~# _# g% l" ]$ N5 U" D* {% O( k& [
p1 += len+1; /* 找下一内存块 */
* y/ r1 C0 p0 ~; p }2 i# s2 r+ ]; N2 s Z. g; v
return NULL; /* 没有可用的, 返回 NULL */
+ x* ^3 j" N% W" L. x# X% ~}
4 F1 J" L w2 Y% |
/ e" k- u7 `4 ^: E) t8 [void small_free(void *mem). \% H$ ^# p3 K* V* [) `' _
{
( S% n/ o d( U' w2 n* v, N2 X *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */1 Z! P+ e3 Y9 p5 y7 j A, z8 A/ f
}
+ q7 z) g$ F- ^( J3 u, n6 J
; U, J" \; |2 d6 s3 Z7 _ |
|