|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
l! D: f) d/ v1 S3 J0 R因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
1 z3 j: V: {, R# @9 W; O正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:4 P; y3 [* C' O
$ y% v2 K: y. J- c$ Z" c3 o. [. k5 {' O5 n) ^/ ^
仅三个函数:
; _2 a# X1 }# T. O3 u( \& a9 f. O0 r" K
<<SmallMem.h>>5 _* E a, r: C2 J0 J) ` [7 p# q
$ Z4 P# S# M; H7 @
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
* l9 e. x( [: V& @& @' K8 y
& I! _1 P" ~7 z1 @$ wvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.2 z& C7 `' W, ^, e$ S! ^
分配成功则返回地址,否则返回NULL. & ~, D' }& h0 Q7 V7 i
0 U- k0 C4 I* P$ q; [. }, uvoid small_free(void*mem); 释放内存块.( ~. ]% i; j. C7 g. ?2 Y7 l* |3 y' ?
0 f9 K* g, z0 h3 e6 G7 \; O8 N. o-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------. I0 V; c$ w8 v; {7 K& @6 N0 ~5 e
<<SmallMmem.c >>9 E* X% X9 d+ E; k6 a: E
, _! D7 f! [ P3 T. D: ^! ?6 o; [) y" ~/***************************************************************************************************
# J8 a& Z7 h1 X& `/ ]& E) s* ]& y Small Memory Managment ..../ o4 s" W, f& N2 V4 P
Copyright 2008 by David Xie 0 G" T6 [0 b' C6 A5 f; @7 z0 V
1 I K: g: ~& J) P; A: W$ b4 o
Last Change: 2008-10-10
: O; l) L0 f! o( |
. H; E9 B" a }! _ ListHead Byte: Bit7 = 1 Free Block8 Y$ }: f1 M- i- Z: u V
Bit7 = 0 Used Block# t& N5 A+ D3 _/ m \
# G5 X/ X! z, u! y: \- f Bit[6..0] = 1 - 127 number of bytes of memory block* Q0 t* l: ], g$ b
Bit[6..0] = 0 end of memory block
I" P# P& G/ _******************************************************************************************************/: I9 `2 m/ l" E8 G+ Z
) v) }) W* M, d' [- e% ]
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.+ y1 ]! K, k- b
#define SMALL_MEM __xdata // XRAM0 b% u6 H) O, ?, H# j9 a& t
% C& t- L9 E& i1 @: q! p//#define SMALL_MEM_SIZE 256+ V: Q/ z9 F5 d* ]) r
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
5 [" y/ K' ]7 q. t0 p* J4 c! P- [& }
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];9 Y2 P2 ]. {5 Y1 y8 x
/ n8 F. N, _0 J% X
void small_init(). v1 E L6 a3 }* H
{) S1 N, A- K# k* B9 o
unsigned int i, n, len;
X7 r* v2 p! H* ~+ D* ^ i = 0;
' i# V z l$ C' S1 ` n = SMALL_MEM_SIZE;: i6 z3 [! _4 C: w9 s
8 ?5 E+ s; |( Z* E
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
2 q9 |7 Z- ?3 s5 } SmallMemory[0] = 0x01;
. k* @, v- Z* f( l) i/ \2 A i += 2;
! L. \' _+ K' z n -= 2;
8 t! X* @/ q/ a% b }
$ V% t0 y' A. f. @
: T+ Z" G3 S3 H7 Y$ @1 q/ `7 w
( K$ z# H+ D' e( i/ M while(n>1){ /* Init Empty Small List */0 ~3 F! d% z( w
len = (128 < n)? 127 : n-2;
, j- T l5 w3 j9 a: v2 I0 ~ SmallMemory[ i ] = 0x80 | len;
5 O4 c$ _; t! z" O' |3 w len++;
7 Y+ b, G9 ?& d9 S4 O i += len;1 y0 w4 Z; d! K" I; D! S
n -= len;
/ z( F5 U" L* q* H! X7 }+ e* w }
+ q4 z" j" \0 H' l7 T/ w SmallMemory[ i ] = 0x80; /* End Of Small List */: Z7 T Z9 O, w* R1 a3 z
}
) R+ P- P" g# C3 y/ I9 V9 O" h* ]+ B$ L
void * small_alloc(unsigned char size)
, V* [/ e& ]- C( \. P8 _) P{
# p/ z. o9 p% h: o A; q ] o- b register SMALL_MEM unsigned char *p1, *p2;- O# k% ]: V' C9 _
register unsigned char len;7 G2 V2 O9 ?/ c$ Z
) v% g* t' s4 q0 |. w
if( size > 127 || size == 0) return NULL;9 A& N4 ?8 w5 D* @& {, p ~
( I- R4 ?1 E" @" S( [6 [" T% c
p1 = SmallMemory;
2 g# a0 Q z* Y while( *p1 != 0x80 ){: I4 N! J- V" G' w) b k8 n( V# A
len = *p1 & 0x7f;8 X- t1 a% | V a% j
if( *p1 & 0x80 ){ /* 找到空的内存块 */' \5 ]- h; i Y. P2 W
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */0 j. W) R0 B1 K
p2 = p1+len+1; / _2 _5 G& U4 k7 T9 P: {. n
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */( Q" T1 P R' G0 T' E5 v% V1 n
len += (*p2 & 0x7f) + 1;
; c8 I' M3 r2 k" {6 x }else{; F; t" n+ o) ^- T7 J' R; G9 @
break;! C, g0 M! _! J1 ?# h
}1 t$ U* V. a2 M: q
}
0 I, [3 \# F' ~: ] if( len >= size ){ /* 找到一个足够的内存块 */1 ^, H, K- m; x8 e& v. w( F
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
$ Z# I, Q' e& ~+ P *p1 = size;
2 V# v: P- q% ] p2 = p1+size+1;
; O6 b* { A/ j& b# ~ *p2 = (len-size-1) | 0x80;+ r* i& X; y' h3 R9 r3 b2 n
return p1+1; w5 I8 Q9 \: z
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */4 F. f6 @' I0 y5 D1 F! a
*p1 = len;. i5 ] @. L. H9 g
return p1+1;
0 N g8 b# I, C# z- c6 V" { }
g1 f8 @8 x5 f }
) v+ L' O: s* ^3 ^: k) Q# c+ B }
~4 t$ t' L8 ]; t: m# p N, w p1 += len+1; /* 找下一内存块 */% O* A! C5 F6 g' C' S& s8 T
}- u* ^) S- n& s2 x5 B- H) n
return NULL; /* 没有可用的, 返回 NULL */
' a, Z+ Q: t! a1 x! Q' J}! K/ i4 @0 U. b4 @ q( F
, Q$ M/ p6 p1 X' `: T- ^1 X' U
void small_free(void *mem)
" v8 Q7 A) c7 S v# u& M7 Z; u{0 h6 @6 R% [" g
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */* r6 n6 ^. \8 X6 ^0 W3 K4 ?
}
% X# `6 Q, m' S0 d5 \; W8 @2 J" f" _4 ^4 w: x
|
|