|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
# A& {3 L7 A9 V因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
0 h# ^7 C4 R c+ L正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:: Y! B3 Y! [ E/ R
2 G% ?' P, v. i& \
$ g& _7 p$ l2 X- x) M仅三个函数:
7 }7 @1 X+ {4 h; S
7 u5 [ x. h7 C<<SmallMem.h>>, L6 y( c# r$ N, m4 W# i$ ^9 `/ x
9 N8 p9 |2 F. o
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
; K2 o3 k- @7 l
" Y( b7 ~# D1 lvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.7 L! Q, Q, {; _2 b4 W( r
分配成功则返回地址,否则返回NULL. & s" h, S! g4 Z
$ h0 Y* E/ }( }% v3 l6 n( j Nvoid small_free(void*mem); 释放内存块.! d, i T* F; L. |$ M% U
, p e' G+ j E8 v-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
; K; y+ P, }; ~4 w<<SmallMmem.c >>) I' ?- j! R3 v8 T& Q5 {2 s; N. H
, Q8 u6 x1 s; x; {/ S
/***************************************************************************************************
# R* I# Q+ z& Q; H( |! _; C Small Memory Managment ....
' ^3 ?0 o1 X$ r Copyright 2008 by David Xie : Y% U8 _- Q' X8 l4 h7 Z
1 O5 Z) m, ?# ?( [- n Last Change: 2008-10-10; o `3 }" w1 g" Y. a
; ~7 C9 j; }' Q$ g, V/ i
ListHead Byte: Bit7 = 1 Free Block2 F# \' z7 Z4 M8 @! m
Bit7 = 0 Used Block: s- w, Z% n2 A( O5 U7 F, F1 R
% ]7 c: l9 |0 T+ ~) ~. p
Bit[6..0] = 1 - 127 number of bytes of memory block1 R0 L, Y- { \2 F; Y! R+ u& m
Bit[6..0] = 0 end of memory block" |9 p0 ]8 L P D; q
******************************************************************************************************/
* ^( F# h7 s% E0 _/ `
. P* `* f' N) S) e#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
U1 ?. `5 ~# Z4 D! c#define SMALL_MEM __xdata // XRAM9 ]/ E/ [6 ]* g0 g* S. u3 i
- G! A+ h* ^5 N; G9 _//#define SMALL_MEM_SIZE 2561 {0 \) f! b# c/ e9 q3 _7 ]: c5 b
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.4 }" P, x% t5 e
" W! ^) J% Q' [) E
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
( j/ H4 g: I) g% x! q1 U7 u+ R* g7 x: K/ [$ A% f" i0 r2 F
void small_init()
+ K# j( ?: ?% G6 q) T! r{
. L' ?! u: U+ b+ E' E( t' A; s2 U unsigned int i, n, len;7 a$ F) f5 S0 O8 x9 t2 @
i = 0;
! v( T8 l( c4 F& b n = SMALL_MEM_SIZE;
: F& ?$ f/ i g& y o- R/ b: @6 j J* D. l$ J E
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */1 ?6 B4 ~2 g5 H& N j \
SmallMemory[0] = 0x01;
7 T0 }4 s/ [* c% o6 s i += 2;
; P6 ?% q; K+ W6 m7 N- G5 y! i n -= 2;% ~# I- m3 T y* ^3 T4 c
} B E! n d5 o* x
* V9 s6 d2 W8 t+ p; p% `6 G: r" Y- H- p. Y. I1 }+ b. K
while(n>1){ /* Init Empty Small List */
) W; _% w* j' `9 i len = (128 < n)? 127 : n-2;
+ J- ~, K( m* M8 }$ Z SmallMemory[ i ] = 0x80 | len;
" N1 |* s# ^ c3 _7 p9 S len++;4 g3 r q0 `, A) k& A$ r# |! ^0 q
i += len;# o& D4 w1 q5 B$ ~
n -= len;' L+ n2 ?8 }# ^3 x, Y1 v/ J
}9 m' b0 _+ ~: W* e4 j: I
SmallMemory[ i ] = 0x80; /* End Of Small List */) {* N- e" t: N5 D
}2 j8 y; L3 s/ }2 ~3 M0 g
y, L& Q! o' Q6 |; p8 F4 f- kvoid * small_alloc(unsigned char size)! c {9 Z! d9 I4 y' d; C+ P7 q0 F
{
# J; i0 k$ d D' ~/ B register SMALL_MEM unsigned char *p1, *p2;
' z: X) t, B& n5 |2 @6 _5 K register unsigned char len;5 v, [' Y- ~$ _' S# t" x1 t
$ h- `/ _8 D: A if( size > 127 || size == 0) return NULL;7 l- T7 E! \3 b! \
x5 d- E0 h% L/ w p1 = SmallMemory;; w6 b. Q* T* V( m; v* I
while( *p1 != 0x80 ){
4 X* B* R1 X7 N. C7 H. e len = *p1 & 0x7f;
9 M1 h5 [% i9 [7 I( D% @) l! ] if( *p1 & 0x80 ){ /* 找到空的内存块 */
3 I) |0 Z' P, l' { while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
+ u! [; D- Z6 E p p2 = p1+len+1; ' J7 W: p- C @
if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */ G" b+ [' d) t( {' K( g6 q2 y
len += (*p2 & 0x7f) + 1;- _( b8 ^7 D! }/ h) N1 u- I% ?
}else{9 L) L$ M5 s. N$ o W
break;
% {, d# E9 y2 k8 j4 o0 \# s* N1 m }( {7 R# b7 R8 d. |; c
}! Z# \6 P5 Y9 x# d4 H: ?7 U
if( len >= size ){ /* 找到一个足够的内存块 */4 Z3 u' D% u4 O) ]% n/ L
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
5 }, ^5 {$ q* o& H. J+ M+ g *p1 = size;/ i9 H- e" [* ~+ b* I
p2 = p1+size+1; }8 P/ u. I0 G* ~
*p2 = (len-size-1) | 0x80;& G( y/ L! D8 i
return p1+1;7 C; d7 d3 V2 P5 o, i- E
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
5 D4 G; D; M5 P8 ] *p1 = len;7 i) {, I# v: y, ^4 z
return p1+1;
; B3 N- M# F4 m2 x& g! v }/ V/ [/ V3 ~3 R6 s
}3 c3 F( n0 [5 O4 P9 w
}5 c' l+ v/ _; q, {
p1 += len+1; /* 找下一内存块 */
7 I/ d9 \ b4 m; e5 F }
9 `; s7 Z+ s. _ return NULL; /* 没有可用的, 返回 NULL */# \% O6 j. R/ `; Q
}; h! I" B L7 a3 r5 ~8 I' T+ _6 N- {
1 l4 z$ W' }, q3 _7 c3 A0 [void small_free(void *mem)0 o8 k7 }! W7 n0 L+ [7 L; S7 V
{
9 h3 k# a. }( P( Q( Y- j *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
1 s) t$ S3 w; V) Z}) L$ T& y* u1 K" m+ s
- m. Q7 D1 Y$ Z+ r/ [- s7 b |
|