技术开发 频道

软硬结合 巧妙平衡WinCE内存成本和效能

        【IT168 专稿】在远古的软件开发年代里,内存是兵家必争之地,开发人员对内存是缁铢必较的。当时人们即使挥汗调校节省区区数十个bytes,都会觉得欢欣鼓舞。随着PC操作系统技术有了突破性的发展,逐渐应用上EMS内存、XMS内存,最后更是使用上虚拟内存,这时调校内存的苦乐俱往矣。缁铢必较的轶趣成为了回忆,我们不再被程序代码大小所限,开发人员从此过着幸福美满的日子。

  但是当嵌入式系统逐渐大行其道时,内存问题再度浮上台面,而且更为严苛。因为嵌入式设备受体积和电源供电能力等因素影响,内存容量很小。如果再沿用PC上“挥霍无度”的编程方式,嵌入式系统一定会因为内存耗尽而寿终正寝。本文从硬件选择和软件调校两个层面向大家展示平衡WinCE内存的成本和效能的策略。当然我们不应指望仅仅拷贝几段代码,就能解决内存的成本和效能问题。诚如“独孤九剑”讲的是剑意而非剑招,需要大家不断地在实践中思考与揣摩,应势而发,见招破招。

  一.在硬件上选择合适的内存类型

  目前PC操作系统流行的观点是:如果内存是问题,多买一点就行了。结果使到所有Windows桌面应用程序的背后都隐藏着一头对内存消耗贪得无厌的巨兽。但嵌入式WinCE系统受到粗糙的电池技术、尺寸和成本的影响,内存容量都非常有限,迫使开发人员将内存消耗量当作发展条件重新检视。结果人们发现内存效能绝不是系统蹒跚之后才需着手解决的问题,它必须一开始在硬件内存类型选择上就要加以考量。

  一般来说,运行一个WinCE需要ROM(只读存储器)和RAM(随机存储器)。ROM是只读存储器(Read Only Memory),ROM的好处是不需要电去维持数据,不过只能读取数据而无法改写。ROM在嵌入式系统里发挥的功能主要是用来储存操作系统。在个人电脑中,ROM是用来存储BIOS(基本输入输出系统)并且只有64-128KB;而在WinCE系统中,ROM大小可以从4MB到32MB,可用于存放整个操作系统以及和系统捆绑在一起的应用程序。在这种情况下,ROM在WinCE系统中就像一个只读的硬盘,存储在ROM的程序能以现场执行(Execute in Place,XIP)的方式运行。换句话说,程序可以直接从ROM中执行而不必先加载到RAM中再执行。这种能力有两个巨大优势:一是代码直接从ROM中执行意味着程序代码不会占据更有价值的RAM;二是程序在执行前也不必先复制到RAM中,这样就只需要很少的时间来启动一个应用程序。

  随机动态存取内存(RAM, Radeom Access Memory)是让使用者自行安装软件、储存数据的地方,也是让执行软件暂存的空间。RAM和ROM不同的在于RAM可以随意读写,但没电的时候数据会消失。RAM在WinCE 系统中被分为两个区域:第一个是程序存储区(Program Memory),也叫做系统堆(System Heap),它是为正在运行的应用程序保存堆和栈的内容。第二个是对象存储区(Object Store),它有点像一个永久的虚拟RAM磁盘。不同于PC上的虚拟RAM磁盘,对象存储区保留存储的文件甚至可以在系统被关闭以后保留。

  作为PC桌面应用程序开发者,你可能会不太在乎操作系统的内存的物理结构。内存可以全部是随机存取内存RAM,或者可能是闪存卡或硬盘驱动器。然而,作为一个嵌入式的系统的设计者,则需要细心考虑在硬件平台上执行的应用程序的内存需要,分配好ROM和RAM的容量配置,并且全面考虑成本、速度和可靠性,以平衡各种目标的冲突。

  二.在WinCE软件层面上提升内存效能

  在WinCE中提升内存使用效能的关键是选择与内存块模型相匹配的虚拟内存分配策略。因为WinCE 实现了大部分和它的老大哥Win32一样的内存API集,所以虚拟内存的调用就是影响内存使用效能的一个关键因素。

  (1)合理调用虚拟内存函数

  众所周知,电脑中所有运行的程序都需要经过内存执行,如果执行的程序很大或很多,就会导致内存消耗殆尽。因此要想获得高性能则需要增加物理内存,而增加物理内存则会增加成本。为了在成本和性能之间找到一个较好的平衡点,虚拟内存技术应运而生,以缓解内存的紧张。和大多数Win32操作系统一样,WinCE也是32位的操作系统,支持4GB的虚拟地址空间。WinCE提供了两种虚拟地址映像方法,分别为静态映射和动态映射。静态映像的虚拟地址空间只能由内核访问,而动态映像的地址空间可以由用户模式的应用程序访问。WinCE系统使用微处理器的内存管理单元(MMU)来处理虚拟地址和物理地址间的实时转换。意思是说:一旦WinCE系统的MMU开始工作,CPU就不再直接访问物理内存了。因此,在一个虚拟内存系统中,应用程序主要是处理这个虚拟的地址空间,并不涉及到由硬件管理的物理内存,应用程序使用虚拟内存不需要知道实际物理内存的位置,只要有内存可用就行了。

  WinCE实现了一个和其它Win32操作系统类似的分页式虚拟内存系统。WinCE虚拟内存页可以处在三种状态:自由(free)、保留(reserved)、或被提交(committed)。WinCE 通过改变每页的保护来保护程序内存,而不是分配给每一程序不同地址空间。WinCE系统通过调用虚拟内存API来为其它类型内存分配内存,例如堆和栈。虚拟内存API包括VirtualAlloc,VirtualFree和VirtualReSize函数,这些函数可以直接操作应用程序虚拟内存空间的虚拟内存页面。因此,要获得高性能的内存使用效能,合理调用虚拟内存函数是关键一步。

  (2)应用内存碎片整理技术

  在一个嵌入式系统中,连续的页面请求可能会带来性能的下降。这是由于在小对象(小于1 KB的数据类型)对内存的频繁的动态申请和释放过程中,由于释放后留下的空洞不够新对象分配,导致不连续的内存可用空间无法被应用程序获得,从而造成可用内存迅速耗尽。这种内存空洞也叫内存碎片。操作系统可能会对这种情况作一定程度的优化,但是由于将内存可用空间整理而导致的效率负担,并不是所有的操作系统都会对此优化。

  不同于Windows XP,WinCE只支持在堆中分配固定(fixed)的块。这简化了内存块在堆中的处理,但是这使得堆在分配和释放一段时间后会产生碎片。当堆里已经清空的时候,仍然会占用大量的虚拟内存页,因为系统不能在堆中内存页没有完全释放的时候回收这些页。一般来说,得益于WinCE操作系统本身优化的内存管理和高度受限的内存使用原则,内存碎片其实并不会对系统的性能和内存使用率造成明显影响。但随着嵌入式设备的内存容量变得越来越大,内存的能耗也是不容忽视的。在WinCE中,虽然不存在自动内存碎片处理,但是微软推荐使用VirtualAlloc、LocalAlloc、HeapAlloc等函数直接操作虚拟内存页,或对本地堆和分离堆进行内存分配操作,而不是使用如malloc、new这类会导致内存泄漏或异常的操作。因此,借助内存碎片整理技术可以关闭连续的空闲物理内存块以节约能耗,从而获得更高的内存访问效能和更大的可用内存。

  (3)应用按需页面调度技术

  一种节约物理内存使用的有效方法是:只加载当前运行程序使用的虚拟内存所对应的物理内存,这种方法称为按需页面调度。当一个进程试图访问一个不在当前内存中的虚拟内存地址时,系统这时会重新从磁盘上将该区域加载到内存中去。PC桌面操作系统一直以来都使用这一技术来加快系统启动速度和优化程序运行效率,WinCE也不例外。在WinCE中,可以通过使用Config.bib对整个系统的按需页面调度进行设置,或通过LoadDriver等函数对单个DLL的按需页面调度进行设置。这一调度技术优化了内存的使用效能,它只在需要加载时才去读代码,从而实现了对RAM的更高使用效率。

  (4)实时监控物理内存使用情况

  系统的内存不管有多大,总是会用完的。虽然有虚拟内存,但由于硬盘的读写速度无法与内存的速度相比,所以在使用内存时要时刻监视内存的使用情况。一般如果只有60%的内存资源可用,这时就要注意调整或释放内存了,不然就会严重影响电脑的运行速度和系统性能。所谓释放内存,就是将驻留在内存中的数据从内存中释放出来。在WinCE系统中,一般可通过轮询或中断法来查看物理内存的使用情况,并在物理内存耗尽前给出警告。WinCE定义了4种内存状态:Normal、Limited、Low、Critical。这些状态的划分主要取决于当前可用的内存大小。

  具体流程是:在WinCE中当出现内存不足时线程首先被挂起,这时系统如果没有可用的物理RAM,需要栈空间的线程就会被挂起。系统然后发送WM_HIBERNATE消息,该消息会向所有的进程发出请求。让它们在不破坏各自内在状态的情况下尽量释放内存,比如释放GDI对象、缓冲数据等,然后限制内存申请的请求。如果在给定的一小段时间内,这个内存需求不能得到响应,就会弹出系统异常。因此,一个经验是在低内存情况下不应该尝试使用大量的栈空间。在WinCE操作系统中,系统能运行的程序数量是由实际内存大小决定的,而不限于32个。当内存不足时,运行新程序将会收到内存不足的警告,并终止进程。因此,实时监控物理内存的使用情况,可以更有效的提升内存的使用效能。

  总之,要想提升内存使用效能就要尽可能地减少浪费。因为WinCE系统不可能为了保证满足所有的内存分配请求而将内存配置得很大。一方面,是因为嵌入式系统对成本的严格要求使得内存成为一种很有限的资源;另一方面,即使不考虑成本的因素,嵌入式系统硬件环境有限的空间和有限的板面积也决定了可配置的内存容量是有限的。因此,平衡内存成本和效能是WinCE系统开发的一个很重要的动作。

0
相关文章