|
|
使用过很多51的开发工具, 但在使用内存分配上,总是不尽人意,要么需要很多的XRAM,要么就是List结构占用太多的空间(至少4Bytes以上), 要么就是效率和速度让人受不了,有些还存在不可知的问题(Google一下就知道了).
8 o$ Z* O9 u- @9 o& C# X4 G因此,不得不自己写一个,来满足目前针对比较少资源的单片机系统的要求,下面的动态内存分配代码, 使用了一个虚拟的List结构, 使得仅用一个Byte就可以维护一块内存, 大大少于商用软件使用的至少4字节以上来维护List.
- G* K$ I6 b0 N. x% Z9 \正如其名SmallMemory, 是针对小内存块来操作的, 对于RAM比较少的8051系统, 非常合适, 至少目前来说,这是最简洁和最有效及利用率最高的算法了.现分与大家共享:
) U' o% B8 M+ a* w. P- N
8 R' x& K8 N7 n- N9 `, @9 [2 w+ R
仅三个函数:
- ]! L0 I" H* o& A6 z' ?/ u0 r4 p4 g' J2 Y# g& M# n
<<SmallMem.h>>9 y5 Q2 \0 U. h# d
* B# H* [' R |
void small_init() ; 初始化, 在使用之前先执行的, 将会把SmallMemory[] 全部初始化为空闲的内存块.
4 P! v+ [3 V( v2 B( {) B. _8 f& n" l2 z7 [5 Y' T$ _' s
void small_alloc(unsigned char size); 分配一个内存块, 注意, 只能取值为 1-127, 此函数会自动对相邻的空闲内存块合并来满足申请内存的要求.
7 j0 D1 D$ t! J; h3 g! V' E7 A( n) x 分配成功则返回地址,否则返回NULL. ! u* p( }* V; A4 S# J3 s% @
0 D, @0 \) r7 \
void small_free(void*mem); 释放内存块.9 ]9 `2 _* H' }$ N; ^! P* ]
/ U1 B. h% W" i) a" ^: c1 v
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2 F& V' S& @8 x% m( }& e<<SmallMmem.c >>6 T N/ _1 Y5 h2 t# {' N% Y3 z
* w7 x! J0 A! G F8 K$ P8 w/***************************************************************************************************
; N! D0 s' n/ K) c$ L Small Memory Managment ....
4 {0 \& E( r3 S8 V, \ Copyright 2008 by David Xie
" a) Y9 s, a* I; @. i( \$ \0 k" Q. z2 q! y
Last Change: 2008-10-10
. _# v& S" X" a5 V, t# q: V9 L9 q0 O
ListHead Byte: Bit7 = 1 Free Block4 e7 y, o( ^2 _6 o6 k) D v$ |7 r) g
Bit7 = 0 Used Block
$ m" q1 N0 [$ s' S8 t- T* Y
1 c+ g2 b) Y: _: x6 w Bit[6..0] = 1 - 127 number of bytes of memory block: C& h4 |% ^8 d- L
Bit[6..0] = 0 end of memory block
8 ^ ?/ I" q& C& n+ ?, G******************************************************************************************************/6 x" t. s4 a! e7 S
: h! p* c1 ^9 n. M K7 P9 X#define SMALL_MEM_SIZE 1024 // 依你的系统来定.
/ q; I p c/ P! |! a#define SMALL_MEM __xdata // XRAM1 V E+ E+ W' o! Q
, a- }8 z: p1 {( S& v//#define SMALL_MEM_SIZE 256
% r% _6 I2 O) M' a$ f" q) j//#define SMALL_MEM __pdata // 也可以支持 pdata类型, 但最多256Byte可用.7 q: j: x; E' l6 i. m% g$ I7 |
* `0 b' f/ t- K
SMALL_MEM unsigned char SmallMemory[SMALL_MEM_SIZE];5 d5 u5 L" o; A
/ W. N# r+ Z3 cvoid small_init()2 T3 n/ e6 K {- ^% O0 t- w4 \
{+ p# Y" Z/ x4 Y$ H: m- I: K, ]" w
unsigned int i, n, len;
2 x I6 u y5 W1 p6 K i = 0;
4 }- M7 O9 \. z" ~8 c n = SMALL_MEM_SIZE;: R3 g( ^: ~* l: R2 i
! g0 D2 U/ v4 ?- d8 g; d if( &SmallMemory[0] == NULL ){ /* if SmallMemory at (0x00), need reserved 2 byte to used, becase 0 is NULL */3 p0 m& u; @; D$ m5 O
SmallMemory[0] = 0x01;
* c8 J c; ]$ X; o i += 2;
9 g/ |" c$ ?9 S: \. I. f/ C n -= 2;
- b4 b* O( F9 k+ M5 |) K! B }
; d( ~- F. f" b8 E" }6 h' z, I" J. y8 y- r$ J5 T a
6 O" L2 J, ]% Z/ O8 N' w while(n>1){ /* Init Empty Small List */
3 `% G' w& Z h) c! d len = (128 < n)? 127 : n-2;
3 }* _2 d( _3 S2 w# j2 J& o SmallMemory[ i ] = 0x80 | len;
6 q" Y4 I0 r! v7 O- b" c% z len++;
& q {2 m' K' s7 J9 A i += len;) t0 Q: Z; S+ y" ]! |: W$ Y
n -= len;
6 q1 o& g) F0 `. k! R) M, B% d3 L }
! f' h. y0 w4 |" P3 p/ O# `; w SmallMemory[ i ] = 0x80; /* End Of Small List */0 ], U; A) U5 A% K& Y d
}2 z- c P% h8 C8 L; H
{; Y% E8 P, w1 p; N/ |
void * small_alloc(unsigned char size)
0 I) w1 U) C+ F{+ W% {' n; t8 s( C Q0 ]- Z, W
register SMALL_MEM unsigned char *p1, *p2;
, ~$ e5 i# n W2 W2 S7 v register unsigned char len;
" q+ M) ]9 P: |8 S1 W9 y" ^8 Q) i+ ]
if( size > 127 || size == 0) return NULL;+ b9 T2 m @ i/ T7 p4 k
; @0 M: v1 J9 p% U, z- w1 z p1 = SmallMemory;% U! S v+ F) h
while( *p1 != 0x80 ){
0 y$ c. F; u2 R$ f7 I! } len = *p1 & 0x7f;
/ J% Z5 W' Q) t' t7 w# A% j if( *p1 & 0x80 ){ /* 找到空的内存块 */
; I! c' u! C6 {! x) _* _ while( len < size ){ /* 如果空间不够, 则再找相邻的下一个空间来合并 */
|3 g0 n2 R) e p2 = p1+len+1;
' O/ S7 ]: J, V. q7 w! d if( *p2 > 0x80 ){ /* 只能合并空闲的内存块 */$ e. S( r% _0 @- Z+ g/ N: u
len += (*p2 & 0x7f) + 1;
, U( P# C. u, G# x Q. O7 f: ? }else{
* J, C- \& [. j- l6 _: o' S break;
) K0 t8 s ~) y5 i+ K }
7 g+ G# M; j& q }6 ^* i' ?+ c8 X6 H% Z. ]% i6 Q
if( len >= size ){ /* 找到一个足够的内存块 */8 Z; n4 f4 ?" G" K# H
if( len - size >= 2 ){ /* 多余超过2Bytes以上的,放回空闲内存块列表中 */- Y, P: t) J2 K! c# P
*p1 = size;% F1 Z& Y2 T. M9 h: _
p2 = p1+size+1;
( L0 C, `, U( q' ?, H# W5 N; A! W' n *p2 = (len-size-1) | 0x80;
" ~4 y& N% G7 [* |! i return p1+1;, a. u0 m. b& u0 ?! E
}else{ /* 多出的不超2Bytes的,则也分配使用了,无法再放回空闲表中了 */
* n& C2 E' @( Y% B8 f2 J0 ? *p1 = len;
6 b5 R1 D# {) |( x6 n0 S return p1+1;- Z# [: H4 Z# h; h, W; d
}
; r, w l' K- M }$ w: Q( T, r, l
}
& \$ V, F5 D3 e: x1 h p1 += len+1; /* 找下一内存块 */
5 f4 Q2 n/ O1 L7 Z9 s }. ^: x3 y! B2 B, R9 A9 o* T9 C
return NULL; /* 没有可用的, 返回 NULL */
: A) a1 h+ w0 {9 q- z( A M}
4 {; h# F& \& }* S* G+ I/ L- k/ m0 H& F; t; s" P" S) r+ W
void small_free(void *mem)
. Y% S3 E; o6 a. h" @' I{
$ F& | R; V$ X1 {, F2 D4 R *((SMALL_MEM unsigned char* )mem - 1) |= 0x80; /* 简单地设置为空块即可 */
1 j) Q$ t8 O) w. X}8 ?% B; { U! C6 I7 b' b t
/ p) k" G e% w. t) P: c |
|