学校地址:湖南省 长沙市 雨花区 车站南路红花坡路口 |
学校地址:湖南省 长沙市 雨花区 车站南路红花坡路口 |
近几天,我在开发一款嵌入式移动产品项目上遇到了一点麻烦。这个应用是arm9内核和WinCE平台,这几天我一直被纠缠在一个内存问题,程序吃内存很厉害,跑一段时间后,内存占用就接近了,出现所谓的假死机。
看任务管理器里面的程序内存使用一直都很正常,但整个系统的内存却在被缓慢的侵蚀,但就是看不出来是程序哪一部份使用了过多的内存。反复的查程序,也没发现内存泄漏,需要不断的修改内存分配策略,很头疼。
1.WinCE是如何分配内存?
(1)WinCE内存环境
在PC上增加物理内存是很方便的,插上内存条后只要自检程序识别,桌面操作系统就能够支持,而在基于WinCE的产品上就没那么简单了。嵌入式设备与桌面PC的一个显著不同是它的应用程序中通常需要直接访问某一段物理内存,这在驱动程序中对物理内存的访问尤为重要。尤其是像arm体系结构下,I/O端口也被映射成某一个物理内存地址。而且与桌面版本Windows相比,WinCE也提供相对简单的物理内存访问方式,无论是驱动程序还是应用程序都可以通过API访问某一段物理内存。
一般来说,运行一个WinCE需要ROM(只读存储器)和RAM(随机存储器)。但在WinCE系统中,ROM和RAM的使用还是稍微有些不同于个人电脑环境。RAM在WinCE 系统中被分为两个区域:第一个是程序存储区(Program Memory),也叫做系统堆(System Heap),程序存储区有点像个人电脑中的RAM,它为正在运行的应用程序保存堆和栈的内容。第二个是对象存储区(Object Store),它有点像一个永久的虚拟RAM磁盘。不同于PC上的虚拟RAM磁盘,对象存储区保留存储的文件甚至可以在系统被关闭以后。
在WinCE系统中,存储在ROM的程序能以现场执行(Execute in Place,XIP)的方式运行。换句话说,程序可以直接从ROM中执行而不必先加载到RAM中再执行。这种能力对嵌入式系统来说,具有两个方面的巨大优势,一是代码直接从ROM中执行意味着程序代码不会占据更有价值的RAM;二是程序在执行前也不必先复制到RAM中,这样就只需要很少的时间来启动一个应用程序。而不在ROM中的但是被含在对象存储区或闪存卡中的程序将不能以现场方式执行,它们将被复制到RAM中再执行。
(2)虚拟内存
电脑中所有运行的程序都需要经过内存执行,如果执行的程序很大或很多,就会导致内存消耗殆尽。为了解决这个问题,Windows运用了虚拟内存技术,以缓解内存的紧张。和大多数操作系统一样,WinCE也实现按需调页的虚拟内存机制。WinCE是32位的操作系统,支持4GB的虚拟地址空间。系统调用虚拟内存API来为其它类型内存分配内存,括堆和栈。WinCE虚拟内存页可以处在三种状态:自由(free),保留(reserved),或被提交(committed)。
WinCE提供两种虚拟地址映射方法,分别为静态映射和动态映射,静态映射的虚拟地址空间只能由内核访问,而动态映射的地址空间可以由用户模式的应用程序访问。WinCE系统使用微处理器的内存管理单元(MMU)来处理虚拟地址和物理地址间的实时转换。意思是说:一旦WinCE系统的MMU开始工作,CPU就不再直接访问物理内存了,对于运行在x86和arm系列CPU上的CE内核来说,必须先确立物理内存地址和虚拟内存地址的映射关系。
这种关系是在一个名为OEMAddressTable的表中定义的,属于静态映射方法。因此,在一个虚拟内存系统中,应用程序主要处理这个虚拟的地址空间,并不涉及到由硬件管理的物理内存,应用程序使用虚拟内存不需要知道实际物理内存的位置,只要有内存可用就行。
2. WinCE与桌面WINDOWS在内存方面的区别
(1)Win32 API 接口之间的区别
WinCE实现了Windows XP中可用到的几乎全部的Win32内存管理API。WinCE支持虚拟内存(virtual memory)分配,本地(local)和分离(separate)的堆(heaps),甚至还有(memory-mapped files)内存映射文件。虽然 WinCE 支持几乎每个Win32 内存管理函数,但是开发人员应当永远不要忘记 WinCE 是与 Windows XP 完全不同的操作系统,这些内存管理API的实现WinCE 具有不同的要求和不同的实现方式。
像Windows XP一样,WinCE支持一个带有应用程序间内存保护功能的32位地址空间,但是WinCE是被设计来应用于不同场合,所以它底层的内存结构不同于Windows XP。例如,WinCE不支持Win32 内存API的全局堆(global heap)。因此,开发人员应该熟悉 Win CE 与 Windows 桌面版本之间的细微差异,在设计应用程序或诊断问题时知道 WinCE 如何实现Win32 兼容性是一件非常重要的事情。
(2)存储结构区别
WinCE实现了一个和其他Win32操作系统类似的分页式虚拟内存系统。在WinCE中,一页的大小可以从1024字节到4096字节,基于微处理器的不同而不同。这和Windows XP不同,Windows 页面尺寸是Intel微处理器所支持的4096字节。
WinCE 通过改变每页的保护来保护程序内存,而不是分配给每一程序不同地址空间。存储在ROM中的程序组在WinCE下当地执行,所以嵌入式系统的设计者能够只占用很少的RAM用于堆栈存储的需要。而且为了进一步的增加应用程序软件的性能,WinCE采用按需求将内存分页,操作系统仅仅需要解压缩并且装入基于RAM的一小部分程序准备执行。因此,ROM和基于RAM的程序的灵活性与速度意味着基于WinCE的设备能够被构造成多种内存结构形式。
(3)低内存环境的区别
WinCE定义了内存门槛(Memory thresholds),它有四种内存状态:Normal, Limited, Low和Critical,这些状态的划分主要取决于当前可用的内存大小。WinCE监视系统自由的RAM,并对越来越少的RAM作出响应。当很少内存可用时,WinCE发送WM_HIBERNATE消息,接下来会限制可能的内存分配。当系统运行需要更多的内存,而又不能满足的情况下,shell会自动关闭该应用程序。
例如,OS首先向非活动状态的程序发送此消息,请求它们在不破坏各自内在状态情况下尽量释放多的内存,比如释放GDI对象;如果没有可用的物理RAM,需要栈空间的线程就会被挂起;如果在给定的一小段时间内,这个内存需求不能得到响应,就会弹出系统异常。简单说是:当系统运行在一个低RAM环境中,应用程序将调整并 小化它们的内存使用,如果当系统需要更多内存时,外壳(shell)会自动关闭这些程序。因此,管理WinCE运行在低内存系统中的程序的方法有很多种,但必须要小心应用,否则容易造成程序挂起或被关闭。
|