|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).. D% P4 Q+ }( t* M7 Y9 n, o
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.. S- _: w) N$ [+ B1 y) |# Q& W
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
/ v4 d: }: P) P+ U0 y
/ q, L/ D3 g2 }0 u7 C2 J) N! S0 y$ t6 r: ^- ]2 `* n! d, S2 |
仅三个函数:
9 u% m2 z* U0 K6 o/ q1 m0 q# y7 R# m
& R. \4 _ c* Y" Q1 x+ i( R" X3 X4 O<<SmallMem.h>>
) Q1 U) p: {' q% V& _# \8 e, {) n8 \2 C5 h; Z
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.2 `/ k. f' o! d$ _
4 h6 X' r z3 Y' |void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
$ j2 D' T! q& ?; S! Z 分配成功则返回地址,否则返回NULL. 6 U; C; B. c6 C% F
, o/ }9 j2 ?6 l2 p9 g0 y j8 uvoid small_free(void*mem); 释放内存块." Q& y4 R( Q8 H& ?1 b \, J' w
; _$ W% N" A' m+ w" w-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* E& u: e$ ]! N. R& K5 }! \<<SmallMmem.c >>
3 I$ f% _2 [/ d% l0 ~. i4 p" y/ d2 @' I
/***************************************************************************************************1 C: A+ D# y; w4 l# I, m
Small Memory Managment ....
! s2 i% i. @& ^/ H$ v/ n Copyright 2008 by David Xie
$ O; ?/ S" T2 z9 g" l9 Z L4 C: r
Last Change: 2008-10-10. T: `7 R# g7 g$ R6 T. k8 Y
3 B# X6 T7 b$ l2 N, ~ ListHead Byte: Bit7 = 1 Free Block, }6 v# k0 P5 K5 I1 h$ E
Bit7 = 0 Used Block
9 t3 |* `0 l" \- R( U% O; \
" \; w( E/ K6 @ T( ?3 I* A! f5 X Bit[6..0] = 1 - 127 number of bytes of memory block
2 K5 m7 Z2 B7 j4 h+ o; h y. X Bit[6..0] = 0 end of memory block0 T5 Y8 {2 L a) T1 e
******************************************************************************************************/1 k2 @# l8 w3 f9 _/ n/ E
) B% k0 f7 g: }: d* w; F. G#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
, E7 n; V- |; F8 p#define SMALL_MEM __xdata // XRAM
( H9 g o" h! f: }0 k; |% d+ A
9 T) `3 e k$ m4 `//#define SMALL_MEM_SIZE 256
y/ m2 ~7 Y A+ V1 D5 B//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.! j$ i% @& i+ U$ \8 ~
1 r- {) G H. B+ L, k" NSMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];8 K" ^. V7 v6 W8 G" r
8 ?) e" S/ U6 X3 O0 ~4 V& o: w6 gvoid small_init()& @9 l. k; y5 n0 M& Y# X2 ?
{ w$ s# o. u |: H, p, R1 W
unsigned int i, n, len;
% G# n; R) E1 }4 Z2 s2 w i = 0;
$ U6 w7 K0 g; T: K& y' ?0 D5 b5 u6 i n = SMALL_MEM_SIZE;) g- H7 s. _- \* m6 O( ?* K
. H$ e1 N& f5 n6 Q( ]8 C
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */) A' u4 e' U0 O. B5 n" K
SmallMemory[0] = 0x01;% ~! r# I) q' n% B ~' A( M. F
i += 2;* W7 V0 D. I! {: r; C0 T n% ~
n -= 2;, T9 d5 K1 S- f) w" e/ d
}9 I1 g/ i7 s9 S( |+ t& Q
! a3 n" }7 i9 b) h2 L5 h
4 M+ m# v% S- h5 m# t1 m0 x while(n>1){ /* Init Empty Small List */! ]/ {6 q% T$ ]$ ?+ x, z% _2 r
len = (128 < n)? 127 : n-2;
7 F V; r; S0 _4 f' x& b( {: o' q SmallMemory[ i ] = 0x80 | len;5 t: ~4 q4 G- z. ^$ N6 f* y. o7 V- _
len++;
2 A/ X/ ?( V. J6 [' j* A0 M4 ?" W0 C i += len;
8 S; {# i: N0 [- C n -= len;
% {3 ~! L) @6 J% \ }
8 t4 U. N; R1 W, d4 G SmallMemory[ i ] = 0x80; /* End Of Small List */
# g- C+ h! a7 _1 `0 n( {0 ~, c}
/ U, ]7 L+ M: G- f' z5 g# a/ Z* E2 b* {
void * small_alloc(unsigned char size)" |6 D" C# ^5 C$ m3 x
{
& l% B7 }0 U* u. @0 s f register SMALL_MEM unsigned char *p1, *p2;1 Z4 B4 W# X! m4 F4 H
register unsigned char len;
0 K9 Q, L) t4 a
4 Q, p' g2 f8 `/ l if( size > 127 || size == 0) return NULL;
* t+ K2 \* s V' u* \0 C1 O5 a7 b* r2 x9 ]4 N8 k) r: I
p1 = SmallMemory;
6 S/ w$ j6 r7 }; L/ {+ l% w; _ while( *p1 != 0x80 ){% U' o. i* v; B2 A; @
len = *p1 & 0x7f;( ~0 V. @! k. S0 R5 A
if( *p1 & 0x80 ){ /* 找到空的内存块 */
7 `- s7 a7 F$ [% ?. p while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
( g0 j( h, _- K) b' V p2 = p1+len+1;
- O7 u( C5 l( h2 N/ _; A0 h if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */ {+ U- [5 x+ |# U6 u: w/ G) {' c) e% {
len += (*p2 & 0x7f) + 1;
; J6 h% T& I7 A+ Z K }else{
6 e9 o# G s. q1 ^! ]4 Y break;
( J; Q- I4 M" t6 Q+ p }1 ?; ?6 j2 V2 \& x. _9 Z
}
( S1 ?3 J% d- f. n if( len >= size ){ /* 找到一个足够的内存块 */$ U: t, u/ ~) o9 |5 b' J
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
g* V# j3 V" k F4 D, \ *p1 = size;8 Q; n) ^0 t$ S+ U( U$ W
p2 = p1+size+1;
' D$ O, F8 X% } *p2 = (len-size-1) | 0x80;
4 \, [, j; D) P return p1+1;
" C3 u4 J* h& C. u8 W A9 p) B+ [ }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
1 Y3 i0 Y' L+ z! } *p1 = len;
1 F( k A8 |) E return p1+1;% |/ I+ b) K, l% r2 q
}+ P) q8 k3 R) `8 V
}
$ G7 D4 s- ]9 e( ^$ e) }* g9 } }
1 P' Q4 P" j7 J p1 += len+1; /* 找下一内存块 */4 A# [# F8 w+ h! ?# W' m" g1 l, K
}
( x! o5 w- F% h# z# I# [" x return NULL; /* 没有可用的, 返回 NULL */. J* q- v! w: {0 j+ V) R
}7 X) o6 G# Q7 n& @( d1 x" M V
; V7 W% Z* }5 p7 w; i: j5 x! Y
void small_free(void *mem): }( l2 |7 j7 t4 p5 P
{
6 K2 ?, D8 F- L7 G' W/ V *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
5 [6 @: w9 E1 N}) p2 @7 a* O" M! x
$ ], H3 T' c$ W( U ~3 L/ T |
|