|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).9 a$ I H( t# `- S$ c5 c
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
" J" e! W- Y1 ^# V, q2 l* b ?: y正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
2 [/ V! H0 G9 |4 W$ h; }
2 u$ v0 i) w5 p2 L/ ]. o: j
+ c6 ~' q* C$ Q' @4 T仅三个函数:! s5 T5 d$ O' ~* s
$ M$ w; a: C4 U6 \# W- N3 t1 E
<<SmallMem.h>>" z' h) ^0 s" y, G9 m3 R/ `. \
& c* @2 c: f# G
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.& ?3 {) v" ~" y" Y( z
0 e" H+ F4 q9 k" t; avoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
% M% [, t% T7 A; G+ `$ P 分配成功则返回地址,否则返回NULL.
! Z: @5 [ J" s9 _6 i2 W% Y2 l" o. e' D; Q7 b" W6 U
void small_free(void*mem); 释放内存块.2 R3 K8 N, G2 f2 g% I- V
7 E& E' P- j5 j
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
$ I- P% k( t9 y$ P3 ^+ c6 P C+ D<<SmallMmem.c >>
; b: ]7 ^- d7 H4 U- u
1 c( d# N. G z Y" S2 X2 M/***************************************************************************************************& H1 E8 ~' r5 \+ W
Small Memory Managment ....( X) E3 q D# P+ c6 i
Copyright 2008 by David Xie
' ^( T4 R( g7 b8 S% I v- f$ D2 c/ k% N, o
Last Change: 2008-10-10- @, M# g8 j2 G/ E
: X8 J! b2 n2 Z" H. a ListHead Byte: Bit7 = 1 Free Block. v7 [: G% ^4 H0 C3 M: @
Bit7 = 0 Used Block
, V! t' v8 H8 r
& L& p4 I! X* R& W: k Bit[6..0] = 1 - 127 number of bytes of memory block
1 F# ?# E4 b# z' E) {2 j Bit[6..0] = 0 end of memory block
$ R2 w- k) `8 \& T******************************************************************************************************/1 m& f: c# ? }
% z% r! O. S. n
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.' o4 Q. F+ g2 O' J+ ?' d- o6 a+ m( S
#define SMALL_MEM __xdata // XRAM
! }% C2 o7 z. K) J, a6 g1 l" ~% ?/ S: f6 l; @9 i
//#define SMALL_MEM_SIZE 256
! ~6 Z: F* o- E. i* r//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
2 ^9 \$ k0 e) S0 p; w4 b' A5 s1 n4 I: {8 A% H( o% P$ o
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
+ B) |& B: u- f5 c p( z# ^0 o( p
; R, F/ y! p n" V6 Wvoid small_init()6 ^# }$ c R, J7 y B* ~0 i# b
{
: U1 S8 }+ z9 P4 C& _ unsigned int i, n, len;$ ~$ u2 i' h8 t- Q/ ]) m* i
i = 0;6 f' f$ y/ s" u8 x$ _
n = SMALL_MEM_SIZE;( i# T5 m3 V5 C" g5 w% K7 E
% |7 l( v1 A( ^: V! E% b. c if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
; W/ K1 e& Q y SmallMemory[0] = 0x01;8 f, N3 y \0 o- q1 ?' o( q$ t7 x3 S
i += 2;
) v# ~4 P8 d3 h: o( c- F6 G/ v n -= 2;
6 @2 J) k: D$ L% o8 J7 t }$ H/ }( s$ \, h; A6 p% n2 ?
* N9 D' l( u& C+ Y# H3 _3 v( {9 m9 U" A# b) ^# ^
while(n>1){ /* Init Empty Small List */) W/ ^% Y: O3 l. F5 ]7 H
len = (128 < n)? 127 : n-2;1 j% I- R& O! W' }
SmallMemory[ i ] = 0x80 | len;+ @8 ~3 {* F- T+ A1 e( Y1 L
len++;( X" p; B6 c% P
i += len;
0 C; B( f. D/ v$ }; m n -= len;
% s: `# F3 S6 J9 A! n' g( S3 ~ }. N, M' V! G( R
SmallMemory[ i ] = 0x80; /* End Of Small List */
; E; Q; P8 a) T: }' e}& s) y* C( k+ Z: L" H- S) _9 a
) L5 k$ W1 H! I* q% n) r* avoid * small_alloc(unsigned char size)7 v9 u2 Y% _* ~& B8 F4 l4 g2 N
{4 u( ?1 h$ P5 O1 Y8 h+ V5 j
register SMALL_MEM unsigned char *p1, *p2;
' _$ C5 G5 z+ q2 ]. w register unsigned char len;
' f8 h/ |- y) ~1 S( g* z; P1 H9 s; D |1 e$ _
if( size > 127 || size == 0) return NULL;
7 `: [/ T. H+ `0 b" z( W% |8 t$ p. p; l$ G u J( I
p1 = SmallMemory;& |. J2 h2 M( z D. v; r5 `
while( *p1 != 0x80 ){
3 R4 y% s- B- h/ y4 g8 d2 A len = *p1 & 0x7f;
2 b" {; S8 P4 O& a if( *p1 & 0x80 ){ /* 找到空的内存块 */
; |% n0 ?) f. y l& R/ K+ x( Z while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
! K4 x. M! Z& X, a+ O+ v3 s p2 = p1+len+1; : D) a' t' o' ^ b {* ^
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
& ~# N' Z; C- U3 k% K; } len += (*p2 & 0x7f) + 1;
3 S" M" ?8 E0 N' V+ \8 b }else{
# {/ Q1 {; b- {7 f break;
6 p G, d0 r! N7 g }8 d( _( Q5 _9 C/ q- Q
}
7 s7 c& g' s7 W j' b" y if( len >= size ){ /* 找到一个足够的内存块 */
3 z* i- h1 P1 n if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
N2 t& c/ V' H& |% Y/ p w *p1 = size;0 ]5 M, @" w6 B l( Z, v1 v
p2 = p1+size+1;$ s% N# _! U0 G9 ]3 t0 ?
*p2 = (len-size-1) | 0x80;
- M3 ^1 P& T5 d! X. ] return p1+1;
! v8 h1 A9 m0 `& X- \4 n+ q- t* j }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */% z; r! t& Z, D
*p1 = len;
, l( m+ U0 i$ Z* `2 C- {- ^ return p1+1;
& j% W7 Q; u7 d3 T6 L T: K: d }
1 n1 U- K/ P0 t: f }
- s% i3 o8 O5 p0 y }
* A( ]* ]& |7 L4 }1 { p1 += len+1; /* 找下一内存块 */; H+ J9 C' F t+ }9 s
}( n* O- G& T5 i% P! d3 y& n
return NULL; /* 没有可用的, 返回 NULL */
. ?3 K) U& E. R- q4 ^" r6 a} @2 \" y& p! C5 F# P% e% m4 ~$ a; a p
" p4 x. l: I+ M$ q
void small_free(void *mem)
5 W8 A. v6 }9 Y2 @0 j{) K! p. k3 t7 }5 H
*((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
( U, E S2 [: n/ @+ p/ P9 K}* }% m9 \! q/ b( h8 X2 L, U0 B
! d$ {8 ^# G, {" V$ ~( G |
|