|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).- v( a1 _" [6 [, v5 Y
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List." N, Q4 k4 r5 B
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
" a) F( I" Y* `
# }7 d r- n q+ g. d
+ `' [4 M5 c1 V+ B1 {3 @/ {仅三个函数:( M' n/ M3 w1 p& n4 Y% L! \* n; ^
7 n0 D& ^& V, Q) K3 o9 \' K1 V7 m<<SmallMem.h>>
( {* z7 q0 A6 g G! T* k& Q% }
: W. E8 g! w2 J& cvoid small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.' U8 g# K6 {+ O- @
& L' `' e1 w) `) B/ r! o, Rvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.5 x2 t, Y K# b2 E3 @/ \) T( W6 G. B% i
分配成功则返回地址,否则返回NULL.
! u6 G% v- T, h( l9 N9 |$ v, x( `/ S
void small_free(void*mem); 释放内存块./ T1 J: u. k' X
- a0 c9 ^3 ]( \' _2 f3 ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
7 ]. k: J9 L/ X) T1 [0 C6 t<<SmallMmem.c >>
0 f1 L1 x) o' A; T! X7 S) j" n. k: s0 P+ H4 E0 z" ~# Z/ A
/***************************************************************************************************
5 N3 N- m% s# Z& r0 v1 k Small Memory Managment .... \; |+ b) B) e
Copyright 2008 by David Xie
: n: E) W8 t% ]8 o1 d
: G r. s& i% z. L5 s Last Change: 2008-10-106 A: C3 y; U/ H' e, [( Z
( K5 ~# r" a! i ListHead Byte: Bit7 = 1 Free Block8 L) u- y0 {6 X+ }
Bit7 = 0 Used Block6 w* r- ]$ y+ r8 h5 v# I7 f
) q. f; X! ~" L6 `$ y Bit[6..0] = 1 - 127 number of bytes of memory block$ E, @! I' z, ^1 l5 y0 v+ g
Bit[6..0] = 0 end of memory block. M4 S3 v, a& K3 P
******************************************************************************************************/( n' C" v6 g9 Y% @8 x# l9 u5 Q
) q) ]! z% m% V
#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
& x# k. l) ^ H9 z1 B+ L/ U#define SMALL_MEM __xdata // XRAM8 [6 x# \& A( e' \
, l: {* {7 _1 d/ f: H
//#define SMALL_MEM_SIZE 256' g- u. V4 p% h! B7 i2 T
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.8 k5 W7 O0 ?% x4 |' p5 L2 f
% e0 A* K' S0 C& B. ^. r0 z: R4 oSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
( \+ ^' Y7 k! `- l4 X. \% y3 o. w- r |6 k5 i2 X
void small_init()
1 @3 S/ @: ] X2 V" G$ m c- ?' I& i{3 p* [8 w7 P% K5 q
unsigned int i, n, len;
3 h, d% Z- A; t% }2 ~! i: R i = 0;! p* v, H8 }) F+ ?2 o0 C. i
n = SMALL_MEM_SIZE;
/ F% v* }- k9 W+ f" y
3 J" w5 m/ n- J" l* u7 | if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */+ ?7 y; p9 u" D. S
SmallMemory[0] = 0x01;
7 b& Z* t( f; P Y; K" @: q/ r7 h7 L i += 2;: N% Q p3 {0 w7 u* }2 f
n -= 2;
) e; ^8 E% ~) v/ c$ f }; f- ^# p. P! B! F
% N' n4 L& r, @0 } X0 Y; e' G$ C d; r
while(n>1){ /* Init Empty Small List */
/ O& {. f! ?& T/ L# N& K len = (128 < n)? 127 : n-2;& Z; d9 R$ z. _0 H+ V( c! Y
SmallMemory[ i ] = 0x80 | len;6 @, j& {; {. ]9 f+ O8 I/ u- ~( M
len++;+ W* \# ]0 G; Y2 @* y
i += len;
\3 T" I2 H1 d8 b n -= len;9 j0 s8 c: u6 t5 N
}2 f0 I; K/ w5 ^$ R9 o
SmallMemory[ i ] = 0x80; /* End Of Small List */- S8 r7 P# C7 j
}
% W+ q7 i6 s8 M
3 O, N* J) Z; i T% `% uvoid * small_alloc(unsigned char size)& p& J6 d& O! T7 t/ R
{- K5 S, |# R. {) |" x& Z* O9 m3 T
register SMALL_MEM unsigned char *p1, *p2;& |1 I- T* |+ o5 |- P
register unsigned char len;
0 m5 t6 ?' i( J& S' ]$ ]6 o2 `8 a4 q" @
if( size > 127 || size == 0) return NULL;
- x5 U4 e% B2 i! J; b$ y v
' t% T c* T9 O) U8 j: | p1 = SmallMemory;
& s& W, \' k8 z. D4 x, Q3 N$ X$ ] while( *p1 != 0x80 ){
3 l* L9 w2 S0 n' S len = *p1 & 0x7f;
$ `( g' E4 H% _0 D if( *p1 & 0x80 ){ /* 找到空的内存块 */
/ T5 l% W; c! k, ^ while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
0 |( @7 q4 P0 a3 [5 q7 U1 P- E p2 = p1+len+1;
) u- H& r+ K& a8 l1 t: D if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
$ ]0 Q, _' V4 ~6 }6 B) S len += (*p2 & 0x7f) + 1;
, a7 Q, N% e! O, t& W. Q }else{0 g! j J% s2 Z t+ s* C5 X
break;
# o2 e2 ]4 F" G4 A/ L }
) ^4 H* W4 }, J. a }
+ j2 K% S+ f% K' }4 ^" l2 r# Q) w if( len >= size ){ /* 找到一个足够的内存块 */$ `) o# [8 f# E. s. F' b
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
) y, F7 n4 C1 C) ] *p1 = size;
" K: k) d& o! E) T p2 = p1+size+1;0 ?0 m# @; ~' [- [: y: O7 s: i( O
*p2 = (len-size-1) | 0x80;
; P9 h) ?" ~' d/ m% H! w return p1+1;
, G, p# W5 H4 y8 l% e; s9 d7 j }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */1 I3 T3 _ g$ m# x
*p1 = len;/ t2 K9 f% _% s/ g2 k
return p1+1;
9 R7 _( i& Z5 d1 H. ~ i }
$ H8 \6 z9 N+ h" W2 a% z6 Z } n- @% W, |5 L- U/ s) E- H4 I
}
/ i! H$ C( U9 e: f$ S p1 += len+1; /* 找下一内存块 */
! G0 W$ `: a6 t" e }
/ T& z) W* n$ n8 |/ k6 H4 T return NULL; /* 没有可用的, 返回 NULL */
9 t# x9 `7 j8 ?$ M; R* E/ t1 V}
* B# q+ ], k# @0 p2 o6 P
/ }3 b6 P- ` m9 J- _void small_free(void *mem)& t+ F' I$ n" t4 B, c7 X2 I
{
7 R# C: n0 J; H7 i0 J *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
; [7 U. N7 c7 U% f1 f}; N w# C( e$ \* W
7 n2 O- r3 f; T) v% B+ Y |
|