|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).. k% w; t$ s/ ~" P. X' V. i
因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.6 i9 c- Y" s2 T+ Z- T: f
正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
" m1 }& f# W5 g4 @% w& |# ~- i+ K0 e& k4 X% k9 E8 P: W
8 q' L: s% }8 k4 E2 }+ ?
仅三个函数:) e2 k5 y* J+ J! n, C/ ?2 Z
" r/ c2 o4 q) r: O! R4 w( M<<SmallMem.h>>1 t# i w) T" }0 J1 `8 v
9 f# ? Y/ T$ N0 _4 Y6 Q
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.* m, K6 o/ v- i; k! j8 V1 p' o
3 |( f* Q% b, I9 F6 wvoid small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.1 c& J! U% T' Y M) s) R* K! M
分配成功则返回地址,否则返回NULL.
$ X3 c8 I+ G, ~& B5 O$ `
: q4 f( Q5 o6 G7 r0 Y1 I) @( [void small_free(void*mem); 释放内存块.
0 p2 e* M1 N( N7 n# P+ v, a! m, y/ g: y- O& Z- f. N" _6 P, J/ t
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------3 S% D' j: k. M8 x5 S1 ~
<<SmallMmem.c >>' ?6 b$ }7 J9 O( u; M: {
7 B2 ^5 \0 \% K2 Y$ ]
/***************************************************************************************************& G! |4 Y& @ n- L3 F8 {
Small Memory Managment ....$ U% s+ d0 E. D- E6 j j$ x
Copyright 2008 by David Xie # k$ j$ d# U c0 Y" ~
) P/ x' J8 y; u5 J A
Last Change: 2008-10-10) V& d. A0 W; w
7 c& o, ] u: E5 b3 |! |
ListHead Byte: Bit7 = 1 Free Block
. t7 ?# B2 I- B; E5 q8 @3 Q$ F Bit7 = 0 Used Block
% M3 F2 Q+ S; H! ^2 j' {+ `1 t& [, @2 H2 ?, i
Bit[6..0] = 1 - 127 number of bytes of memory block: z9 R4 [( U, p9 C
Bit[6..0] = 0 end of memory block
# B( C+ c: O8 W5 [" @" r* K******************************************************************************************************/0 J( t& g! ?- [' V- h
3 \! b: r0 x: x#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
8 p% p7 `* Y: L0 L( `' j! y#define SMALL_MEM __xdata // XRAM* W8 P/ Z6 M. |* t6 Z) ~# p
( {3 G4 } H m) Q$ V1 H/ k. w
//#define SMALL_MEM_SIZE 256! N9 F1 U& y' C
//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.
7 T+ P' A. Q( b( Z3 r* q0 f0 W0 I
3 B3 R; g6 S$ g% ]9 D: l& {SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];
/ d3 n9 ?( o4 E! |+ G
3 J L/ d, P! _( x- s6 V( M( E: Nvoid small_init(); f6 F d2 ]9 X3 e* Y
{
* F; ^# m: N# ~1 H M u/ M* i unsigned int i, n, len;
% |) F* G& [ h$ v i = 0;* b0 q% v' Z( L: c8 L# r: b2 \4 {
n = SMALL_MEM_SIZE;; W4 g6 |' b% y; t* |2 M
* F+ ?: C: B# ~ k! N g! C% k' i( M' v
if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */
4 U1 I `* b: k+ D SmallMemory[0] = 0x01;) r: w' U7 S( ?) v: h- b/ ]
i += 2;
" c5 a; a1 J5 Y; I n -= 2;; J/ b5 P# f# }
}
" Z' [ {0 j u1 Q$ h
5 z$ }. ^$ C$ D) u1 {" K& P" O* |4 ]3 v5 L2 E5 T$ K$ X. H
while(n>1){ /* Init Empty Small List */7 w$ f" _+ t5 b' U
len = (128 < n)? 127 : n-2;) p; p+ u# C- L
SmallMemory[ i ] = 0x80 | len;
8 \* D$ B; O: {! \- Q$ f h len++;8 V; O4 \1 n7 G
i += len;% @* G8 N J& x9 B# c
n -= len;
3 b6 T( W* e) t& R+ e' [ }
! v @. w, \( S8 X4 [# c, z V" f SmallMemory[ i ] = 0x80; /* End Of Small List */. f, [: t3 j' @ ?3 s( |. ?
}
4 G0 b. o0 L9 |- `7 N/ r! x8 a2 N- f" q# S, Y% j0 ]8 W2 d
void * small_alloc(unsigned char size)
$ Y6 F7 }0 `8 @! H* b/ n3 j{5 N( H# P- U) b/ C' A
register SMALL_MEM unsigned char *p1, *p2;. o8 `0 o& d: J' E5 g5 Z
register unsigned char len;
& x) j Z2 A. M+ u0 O" c2 ^( Z# Q$ o2 n5 n0 p
if( size > 127 || size == 0) return NULL;
) b* t8 B/ y9 M0 s$ b( ]3 y6 X( h e# {/ B: T; Y* R+ _
p1 = SmallMemory;
3 W; X6 [* V6 ^4 v6 h while( *p1 != 0x80 ){
5 K0 p! n5 u# ^ N; _ len = *p1 & 0x7f;
: R) f8 \; M. @0 A2 V: |" p if( *p1 & 0x80 ){ /* 找到空的内存块 */( {8 C8 ` w: F( D6 d! q, v
while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 *// A, c, t" p# J
p2 = p1+len+1;
8 m( B/ N! J7 F8 O Z% c# a if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */
2 B+ a+ r# h$ O' o9 | len += (*p2 & 0x7f) + 1; J1 \& d4 s: d* s3 f8 T( z
}else{
8 R9 {5 C- V! u3 e break;
9 [& t. q9 w7 O0 `: _* U }. z; t9 c" F2 D# k
}
7 n0 i# C7 m- ^( h1 q% H4 m5 E if( len >= size ){ /* 找到一个足够的内存块 */& y* n# D ]5 L8 C b3 I
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */
' Z$ S( c3 I% G* o: q- O *p1 = size;5 B% j2 Y( `' o. p; E' h6 Y& t
p2 = p1+size+1;
& k6 d4 n4 a) j/ z *p2 = (len-size-1) | 0x80;1 E) ^( W& d3 ?- b# b5 ~
return p1+1;
m4 d" N8 `! V2 L }else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */5 A. M4 h4 O/ ~$ j! q% n5 B
*p1 = len;- q6 y, Q9 Q* N3 i
return p1+1;
$ b) l# X3 I$ m& }# I; J }: S* Z1 X2 H2 g* u) M
}
" e( A- y, N& S* Y: i7 S }# ]. D) X& @2 D1 x2 z( M$ m9 \
p1 += len+1; /* 找下一内存块 */# k+ u! c1 Z3 E! t5 x3 g
}
5 H9 P, H8 M' y/ _& c* ~ return NULL; /* 没有可用的, 返回 NULL */" [( h, b. P' p9 A! |
}
9 N% I) @ a6 u. Y& P5 q5 Y! P+ A0 V
void small_free(void *mem)9 V. S" U4 X* z: v
{
; [; {+ u8 P2 N# D *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
/ ?# Z4 L0 o9 b b: w5 l}) k( U) v6 r3 e- F' d# a( W
, A1 m' N) g2 f9 F* ^5 t |
|