摘要:探讨嵌入式开发对内存管理的基本要求、嵌入式开发内存管理的关键问题以及给出一种VxWorks内存管理方案,即把除VxWorks系统保留内存以外的内存分为三种类型进行管理:固定大小的缓冲池、动态可变的堆以及由各种固定大小的缓冲区组成的队列。 目前,针对有内存管理单元MMU(Memory Management Unit)的处理器设计的一些桌面操作系统,如Windows、Linux,使用了虚拟存储器的概念。虚拟内存地址被送到MMU映射为物理地址,实际存储器被分割为相同大小的页面,采用分页的方式载人进程。 大多数嵌人式系统针对没有MMU的处理器设计,不能使用处理器的虚拟内存管理技术,而采用实存储器管理策略。因而对于内存的访问是直接的,它对地址的访问不需要经过MMU,而是直接送到地址线上输出,所有程序中访问的地址都是实际物理地址;而且,大多数嵌人式操作系统对内存空间没有保护,各个进程实际上共享一个运行空间。一个进程在执行前,系统必须为它分配足够的连续地址空间,然后全部载人主存储器的连续空间。 由此可见,嵌人式系统的开发人员不得不参与系统的内存管理。从编译内核开始,开发人员必须告诉系统这块开发板到底拥有多少内存;在开发应用程序时,必须考虑内存的分配情况并关注应用程序需要运行空间的大小。另外, 由于采用实存储器管理策略,用户程序同内核以及其他用户程序在一个地址空间,程序开发时要保证不侵犯其它程序的地址空间,以使得程序不至于破坏系统的正常工作,或导致其他程序的运行异常;因而,嵌人式系统的开发人员对软件中的一些内存操作要格外小心。 1 嵌入式系统中对内存分配的要求 嵌人式系统开发对内存分配有很高的要求: ① 内存能快速申请和释放,即快速性。嵌人式系统中对实时性的保证,要求内存分配过程要尽可能地快; ② 内存分配保持原子性,即可靠性。也就是内存分配的请求必须得到满足,如果分配失败可能会带来灾难性的后果; ③ 内存应该各尽其用,即高效性。内存分配要尽可能地少浪费。不可能为了保证满足所有的内存分配请求而将内存配置得无限大。 2 VxWorks内存管理机制 VxWorks采用用户程序、内核处于同一个地址空间的内存管理策略,软件开发人员在开发程序时必须保证不侵犯其他程序和内核的地址空间,以免破坏系统的正常工作或导致其他程序异常运行。内核负责为程序分配内存、动态分配内存和回收内存。VxWorks为用户提供两种内存区域:内存域region和内存分区partitionregion是可变长的内存区,可以从创建的region中在分配段segment,region的特点是容易产生碎片,但灵活、不浪费;partition是定长的内存区,用户可以从创建的partition中分配内存块或在某个内存分区中再创建一个内存分区,partition的特点是无碎片、效率高,但浪费。通常,VxWorks内核和应用程序对内存的操作是基于内存分区进行的。内存池是一块连续的内存区域,包含一个或多个内存块。内存分区包含分区自身的描述信息(一个结构体)和一个或多个内存池,描述信息保存在系统内存分区中,内存池是该分区实际拥有的内存空间。内存分区刚创建完毕时,只有一个内存池,以后用户程序可往该分区中添加内存池。内存池之间的地址不一 定连续,VxWorks在启动过程中会创建一个包含系统内存池的系统内存分区,如图1所示。VxWorks的内存管理采用自由链管理内存空闲块。用首先适配算法动态分配内存,内存释放时,采用上下空闲区融合的方法,即把相邻的空闲内存块合并,没有清理碎片的功能。 3 对VxWorks内存管理的改进 改进的缓冲区管理模块的作用在于加强VxWorks实时操作系统对内存的管理,并为上层应用程序提供所需内存申请和释放工作。因此本改进模块位于VxWorks实时操作系统模块和应用程序模块之间。 CPU实际物理内存在bootRoom启动时划分为两部分:VxWorks内核操作系统内存和保留给用户管理的内存。为了便于管理,对为用户保留内存作进一步划分,使用memPartCreate函数创建两个内存分区:一个分区用来生成预先申请好固定大小缓冲池;另一分区以堆方式向上层提供的缓冲池。这样就把物理内存划分成3个部分: (1)Paal:VxWorks系统内存,在物理低端; (2)Part2:预先申请好的固定大小的缓冲池,每种固定长度的内存缓冲区形成一个队列; (3)Pan3:以堆方式提供给上层应用程序的缓冲池; 内存划分如图2所示。 3.1 不同大小固定长度缓冲区管理 为了避免内存碎片,我们采用预先分配内存块的方式实现对堆内存分区进行管理:分区内的所有内存队列,每个队列管理一定数量大小相同且已经申请好的内存块,这些内存块永久占用。然后对每个内存队列管理数据结构进行维护。上层应用程序调用模块接口函数从缓冲池中 申请和释放。每块缓冲区的用户区填充默认内容。
3.2 堆方式内存的管理 对于堆内存的使用,我们对VxWorks的两个内核函数memPartAlloc()和memPartFree()进行了封装,并在调试版本中加入信息,如图3所示。 图中:BLOCK- HDR表示内存块头,OAHEAD表示块附加信息头,pbuf指向实际的堆空间,size为堆的大小。 3.3 快速内存分配管理 对于协议等存在大量、快速地申请/释放内存的操作而言,在系统运行一段时间后内存都变成了碎片,再申请大块内存时容易失败。提供一种快速的内存申请/释放的方式,并且最大程度地减少系统的内存碎片。提供64/128/……/524 288大小的内存使用快速内存分配管理机制,则在一个大的内存块内部进行内存使用,申请/释放时不涉及到系统对内存的拆链/建链过程,比较快速,并且对释放的内存进行合并,保证系统有尽可能多的大块内存。如图4所示。 4 小结 许多嵌入式应用开发在实时操作系统提供的malloc()和free()函数的基础上编写自己的内存管理方案。编写这样的内存管理方案,一方面可以减少对malloc()和free()函数的依赖,统一内存应用接口,从而避免此之带来的内存碎片、时间不确定等缺点,另一方面可以增强程序的查错能力,减少内存使用错误。对于在嵌入式系统中广泛存在的数据库类型的内存需求,把由用户管理的内存分为固定大小的缓冲区、以堆方式分配的缓冲区和不同固定大小内存队列的分配方式,体现了内存管理的优越性。
|