|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
3 c( j% G# j; h/ y因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.6 K& i$ X1 {; j% ?( u
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:5 n+ [$ p1 z* B& O% q( |0 \" q% E
; Q) j4 B6 G. j
/ ~ I h; G5 Z6 H: V- W/ E仅三个函数:$ z+ s* {5 D' E
3 t& q, O' K; i p8 G<<SmallMem.h>>
/ e" r5 \- H/ z5 ]9 v/ L1 @. Z- S# M3 K
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
% j: a- z, b' w/ k q; j- _: Y0 s8 w/ X# N& u3 G
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
$ A8 B3 K* R# M9 a# ?' v 分配成功则返回地址,否则返回NULL. ' X& j& M+ X" L* c e
- y4 |" s( q6 g, X' ]
void small_free(void*mem); 释放内存块.$ l# i0 h& v( s! T. ^& L0 o
( U6 u+ O( }0 k% u) O. U7 Y( v
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------% x3 |2 q6 s+ t+ O0 a
<<SmallMmem.c >> {9 b5 _) x! N1 I8 m* G$ x5 T, z
' c1 y- V- O4 P& f# _4 p9 j- O% E/***************************************************************************************************% D4 W% u2 `6 O' J
Small Memory Managment ....6 |3 F p3 z$ t% }" B+ \
Copyright 2008 by David Xie 1 b1 J6 e L+ @, ?2 h. ]
& K8 b. @% O+ y7 k; a
Last Change: 2008-10-10
3 n' R/ V Z6 @$ E. Z- l$ z% P% S$ v& j$ h9 w+ c& j
ListHead Byte: Bit7 = 1 Free Block. z* O, z# c: b. s; p0 [
Bit7 = 0 Used Block9 s7 S- U# d. P
: s% F* l" Y2 y
Bit[6..0] = 1 - 127 number of bytes of memory block; W1 ]; R2 p; S+ t, M) G8 R8 Q7 W3 U
Bit[6..0] = 0 end of memory block* E# j/ y" L: X& N
******************************************************************************************************/
6 t/ }. W+ T" Y! o! c0 S
; s6 t* Y, e* H" M2 B A5 h#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
$ e; F4 o$ z- O4 r#define SMALL_MEM __xdata // XRAM
# \4 `7 u; v. f2 ^% j6 _+ B; d. m! c' ]1 k0 N1 v% s
//#define SMALL_MEM_SIZE 2560 `$ Y: i8 r9 t- t# @
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.+ V- ?+ \/ h# n* z: _0 \8 m
, S: u8 l: m: ~. [3 ~5 MSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
! g& g4 n/ i) |/ }* ^' c( S) {# t
void small_init()! w3 c W: F! I/ e9 F Q
{0 x6 q4 e; }4 _1 u! _
unsigned int i, n, len;
1 u5 m9 Q6 I# p" C* S( R i = 0;
+ Y" s+ \) ~4 X, C% |, }0 W n = SMALL_MEM_SIZE;* ~$ x6 M! \* L0 ^( w
' g8 B. k: J& ~6 {) Y1 J+ D6 p if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */5 i6 y5 F0 C P2 F* a3 T5 f
SmallMemory[0] = 0x01;
7 [ T% Z# l8 E i += 2;
* j. _6 l) m+ H9 V/ w+ x& z1 X n -= 2;& V' G/ |, I, U' i: {/ E: H B) s1 v
}2 {7 u( Q* u' K
& I9 J: w( |7 l0 q( I" u! e4 A: S; h- @) H1 c8 Z3 z; D, u
while(n>1){ /* Init Empty Small List */+ a) r; @" |% X& f7 U# l0 {
len = (128 < n)? 127 : n-2;5 ~' Q r1 X- N, p& H
SmallMemory[ i ] = 0x80 | len;( T+ M# r' E2 J& f* I+ N
len++;
8 y1 Q' o* F' Z6 T3 n0 H" K i += len;* ^/ C9 h* @* |2 T1 q' `/ \5 b
n -= len;7 k5 g% A/ ~. R6 W1 y- g0 {7 @
}
4 ?5 w d3 w2 b' q* k9 V SmallMemory[ i ] = 0x80; /* End Of Small List */
$ a0 a/ I9 t9 |# b: c9 F}4 n* p6 j$ a4 H$ A" M
6 z: J' }- ?# i, \- d1 G
void * small_alloc(unsigned char size)
; W) f" B+ {( ?2 n{
* T( V/ N4 T7 D$ V4 w9 _ [, [ register SMALL_MEM unsigned char *p1, *p2;
8 a. `# G. P' G! b) K register unsigned char len;. X. e0 |( I8 \" {. o
3 P5 J5 m7 {7 f( v' s& [ if( size > 127 || size == 0) return NULL;' L; b0 G* U1 @* T1 O
: I3 p; h' A/ J& Y
p1 = SmallMemory;1 L/ r+ o6 [0 U/ A5 P8 w
while( *p1 != 0x80 ){& y4 L9 t# |8 f+ n
len = *p1 & 0x7f;
% d& {3 n+ S( q8 t" ~ if( *p1 & 0x80 ){ /* 找到空的内存块 */$ i) h3 K4 `$ H
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
6 c: {+ `2 ~5 @4 {+ K; y/ v: {, k# x$ o p2 = p1+len+1;
@; |6 t( g$ D) T4 P' w8 f) H if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
7 Q; Z0 t6 p* i) j* E! z% x len += (*p2 & 0x7f) + 1;) r6 s; V4 X: a Y& u& q8 b/ B
}else{
9 `* w. G9 \9 { _! N, p break;
' u9 l: z% I$ {" R }
7 q* z! u1 o* N }9 K9 m5 O1 L" a
if( len >= size ){ /* 找到一个足够的内存块 */
4 K) Z; R9 ]8 L- p# K, V if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */! C: `1 J, \' B7 u$ V2 t1 \
*p1 = size;( f0 e/ J" J# _
p2 = p1+size+1;) D M/ o# i% ?) T4 I u2 C
*p2 = (len-size-1) | 0x80;0 y! i. }9 @8 c: V# D% b) h! ]/ \
return p1+1;1 k5 l: i3 t" O4 W
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
. e d M! {1 \4 d *p1 = len;
, Q: B; F6 }. k6 e return p1+1;/ J6 O1 h/ I+ ]0 P$ Z5 P; ~( J1 u" e
}
' G, a# | i: ] }* D! O2 a X* \" \" s
} P* g2 G4 ] h' F
p1 += len+1; /* 找下一内存块 */
0 S) U0 Y8 B) n' d+ H6 X- q }
8 |) S. u0 A6 `& x* ~6 U1 B- p return NULL; /* 没有可用的, 返回 NULL */
- B, b6 o+ y8 l- M, w}
( `! u# s+ O5 p
+ y$ @3 Z+ l+ G' ]% _# s+ Yvoid small_free(void *mem)
' @2 \: ]7 X2 q& d6 i{3 S# K) N" z5 `4 L
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */) \% ]0 `- U& _" S7 z* R
}
) U: c4 B* c* z$ d* |( t) {5 c* b" L& D e
|
|