内存管理在嵌入式系统中是一个比较重要的问题,如果处理不好内存资源的管理,那么系统的鲁棒性将会大大降低,更严重的话系统将会无法正常运行。过去我在DSP平台上开发过tcp/ip协议栈,遇到过此类情况,所以在此我想对嵌入式系统中的内存管理方法进行总结,重点说明为什么不能在嵌入式系统中应用malloc函数。
malloc在嵌入式系统中应用的问题
在嵌入式系统中采用静态内存分配的方法比较可靠,但是,很多应用需要进行内存的动态分配。提起动态内存分配,大家不约而同的会想到malloc函数,该函数是C语言中定义的标准内存分配函数,一般的C语言编译器都会提供该函数,例如在嵌入式应用中常用的编译开发环境Keil C、CCS以及ADS都会提供此类内存分配函数。
编译器提供的malloc内存分配函数的实现基于堆算法。动态内存区域是一个堆空间,分配内存时总是从堆的头部向后查找,分配一块满足大小的一段空间,释放资源时检查是否可以与堆空间中的临近空闲资源合并成大块,如果可以合并,那么堆空间中的连续资源将会增加,否则将会产生一个新块链接在堆空间中的链表中。
在系统初始化时,动态分配的堆空间为一整块资源,随着内存资源的不断分配、释放,堆空间将会被不断切分,切分成很多细粒度的空闲块资源。当堆空间被切分成很多小块时,系统就不可能再为大块需求分配资源了。虽然细粒度的块聚合起来能够满足应用需求,但是,堆算法已经无能为力了,就会出现malloc分配失败的情况。
从堆算法的本质出发,我们就可以认识到malloc在嵌入式系统中应用存在的问题。当系统长时间运行之后,内存资源将会变得越来越零散,运行之初大块的内存已经不复存在,可能只剩下很多小块的资源。所以在大块内存需求的情况下,系统将会出错,所以系统的鲁棒性将会随着系统运行时间的增长而下降。因此,在嵌入式应用中不建议使用malloc进行内存分配。
小型嵌入式系统中的内存管理方法
小型嵌入式系统中经常采用分块的内存管理方法。其思想比较简单,即将内存资源分成若干块,当需要内存资源时,获取一个块资源,使用完毕之后再将块资源释放,归还给系统。采用分块算法的一个问题是:如何确定块大小?因为系统中的应用对块大小需求不一样,如果块过大,那么利用率下降,如果块过小,那么无法满足分配需求。
针对该问题,提出了块资源池的概念,每个池中的块大小都不一样。应用提出内存资源需求后,系统根据需求到合适的池中得到资源块;释放资源时,再将资源块释放到对应的池中。在实际的uc/os操作系统中,就采用了这种块资源算法的内存管理方法。虽然,分块算法在效率上不是十分高效,存在块内碎片,但是,对于简单、小型的嵌入式应用,这种管理算法已经足够了。
大型嵌入式系统中的内存管理方法
目前,最有效的内存管理方法是虚拟内存技术,通过虚拟内存技术可以将逻辑内存和物理内存分开,程序运行在逻辑内存空间,对于每个任务而言都能看到一个很大的内存空间,逻辑内存和实际的物理内存通过页表进行动态映射。由于虚拟内存技术涉及到页表的映射查找,所以如果采用纯软件的手段,那么实现效率将十分低下,因此往往需要硬件的加速。这个硬件加速单元就是MMU(memory management unit),其本质上就是一个lookup table。因此,采用虚拟内存技术的嵌入式系统都需要CPU集成MMU,否则该套机制很难实现
|