|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
! f) T- ~, `. C因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
1 N: T1 I2 R6 }& ?5 i正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:% w4 d1 x6 i, Z+ a' m
K, h% ]) x, Y2 U$ \
7 K% U8 q1 X, P, s0 Q9 d仅三个函数:' z Q4 k; Z0 [/ L% B
& j& J5 {. j" b% x. `4 [ U" u<<SmallMem.h>>0 }& S$ ^) J6 D, k
& X5 V4 S7 d1 D! X9 j0 N
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.# X2 ^& _2 [4 M( B
. _( \# W' f+ |( evoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求., ?6 A' Z6 q- Z/ t/ ^: a
分配成功则返回地址,否则返回NULL. 4 q7 U$ y- b' b
`2 \* o3 M5 K0 }; Qvoid small_free(void*mem); 释放内存块.. V' J0 g8 T2 F: L2 m8 d
+ `5 G* H& n+ M9 i# z: M' M
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Z" s H2 y4 u
<<SmallMmem.c >>1 N+ u# w4 T2 b+ Y& B, l
! @1 r, @1 R4 j+ F: K/***************************************************************************************************8 Z s" L0 j6 Z. M
Small Memory Managment ....
6 _ n, d9 W, p: n8 z6 | Copyright 2008 by David Xie % w. y+ s: c$ r1 B' x$ y. [* e# H
( X' _) [& f( X) @ Last Change: 2008-10-10
* v% E/ h! z/ O' E- I
+ D$ O" k: U/ T3 k; S+ s ListHead Byte: Bit7 = 1 Free Block
$ W4 w3 x8 s4 } Bit7 = 0 Used Block
6 n4 Y; G& x$ n: l+ X9 f
/ c; o5 d% C% l4 _7 j8 W+ Y2 L5 r Bit[6..0] = 1 - 127 number of bytes of memory block) I8 H. x' C3 A
Bit[6..0] = 0 end of memory block
% D$ m/ E4 a7 D******************************************************************************************************/
5 r9 `; T2 D; K0 G
% j2 e" _; G/ A2 F% y#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
+ F/ M% Q7 o) j; C6 X1 O2 z |#define SMALL_MEM __xdata // XRAM
" j& B5 w1 O- {& S# t- @2 G Q: \$ ?, u+ e
//#define SMALL_MEM_SIZE 2565 _' ~# g0 i; Z. @9 j
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.6 L2 o, L+ O9 B b$ Y- K+ ]: c
7 l6 _% B p3 I5 KSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];; P0 N9 Q A; \: h
, |8 ~: }2 `7 W9 }* r
void small_init()3 n% G1 {2 M0 l9 e- s
{
( v# D" `" r& m+ u+ z+ I: a8 x( C unsigned int i, n, len;3 G5 u% @% f3 l% u
i = 0;$ A- R$ I! Z* H7 @' I r
n = SMALL_MEM_SIZE;! p- `: @- I' i5 S0 d5 i8 |0 ^6 Y( L
; T# P2 z, b/ m7 t
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */& l- |" J* r0 L5 [
SmallMemory[0] = 0x01;
* C+ m, y9 n$ [3 a i += 2;& g% r e/ M p6 a
n -= 2;; j- A4 |$ F% q: o: P
}& |0 B& f1 i0 F' U
# I1 y |! E [& q/ ]9 E- z6 K4 K3 U- t7 F& ~5 `
while(n>1){ /* Init Empty Small List */$ t( B+ k- R. h- C8 P: l* X/ A
len = (128 < n)? 127 : n-2;
4 `+ z }8 N; [/ e! D" |! Q SmallMemory[ i ] = 0x80 | len;
; ^) v$ G1 m c6 B {. d len++;
& s: S2 \. \# {- H! s' x i += len;
. U z0 E l8 J b9 v, D+ I n -= len;! ^0 D; b H z2 c
}
1 ]' ~$ N1 @- W5 m SmallMemory[ i ] = 0x80; /* End Of Small List */
% U: K2 \6 X0 `0 ^" v3 [ q5 K}5 c9 c) O( Q9 J+ b& w$ h# l
1 t5 Q9 h% X3 X" Q$ p5 qvoid * small_alloc(unsigned char size)
1 T* y& V& j6 e( U3 m" t" i9 z{
% X9 S7 l* s/ ^2 C/ {, S register SMALL_MEM unsigned char *p1, *p2;
8 S9 {1 {# p+ p* N5 X register unsigned char len;
* C) i/ m4 X! O8 d! C- K
' i* e8 y8 H- g3 E, X# R if( size > 127 || size == 0) return NULL;, \4 `. d2 q4 [( [. I, w
: y9 e' q8 N0 y% v4 t; w
p1 = SmallMemory;
. a6 _5 Q W& `; z& g while( *p1 != 0x80 ){
3 G0 \8 E _/ j9 m5 q len = *p1 & 0x7f;1 X, Y6 T" p0 `
if( *p1 & 0x80 ){ /* 找到空的内存块 */
* k# a, i. Y5 {5 q; z) l" K while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
0 Y: U$ S! \$ f6 {2 f3 A& R p2 = p1+len+1;
( E3 t! ]' }! f if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
+ m$ [& c# F4 a% i2 x$ C) J len += (*p2 & 0x7f) + 1;
. w' N* `7 J' G" O" G }else{8 `6 t0 W; |9 r4 E
break;
9 I9 M2 G3 \' u3 r: I2 z/ w1 @ }1 M5 \1 H* Z; v# q
}
) w+ B3 r! @* P if( len >= size ){ /* 找到一个足够的内存块 */7 y+ n+ ~/ }& ` ^
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
; f% ?* \! c( X7 o2 I- M$ f *p1 = size;
5 \" [5 h5 q( D p2 = p1+size+1; \7 `) l6 m; N: i& P( G8 U1 ~ U
*p2 = (len-size-1) | 0x80;
6 n9 u5 o" V! \ return p1+1;0 j( q+ p n& |0 [
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
7 g( L: S% F. L+ C" E% e( I5 x *p1 = len;
1 g/ U- y$ j& @& m return p1+1;2 ?' U0 c$ z7 ^7 w
}
* r h0 M$ c' {) p }% l+ x) v0 g2 X/ P8 ]( G
}
' [8 X7 G8 l' r# V/ ?3 r! J8 D p1 += len+1; /* 找下一内存块 */1 c6 t2 {% h4 V. r
}2 r( h) R! S- ~# k4 `, N8 x
return NULL; /* 没有可用的, 返回 NULL */ r6 H8 @0 I G! b6 V1 j8 M
}
7 ~6 L' i" q) L5 J& ?) ^
9 u$ v" X" q+ \void small_free(void *mem)
' }+ p+ l2 ^3 J) s% o* w{5 E8 O5 N( T7 N. u) b9 \
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */: K8 D% i- W8 H3 X8 ~
}1 {! ^& C3 ]' V
0 u" s8 ` [& o& G
|
|