|
|
|
基于BREW手机游戏的内存管理研究 胡耀华(北京交通大学计算机与信息技术学院 北京 100044) 【摘要】随着手机技术的发展,手机已不仅是通讯工具,其程序系统逐步成为游戏开发平台。目前,手机游戏平台有很多,其中最有影响力的是高通公司的Brew和Sun公司J2ME。本论文介绍了BREW手机游戏内存管理的一般技术,针对RPG的一种新的BREW内存管理技术,包括其原理和实现。 【关键词】Brew
RPG 内存管理 游戏 手机 1
BREW简介 Brew (Binary Runtime Environment for Wireless,无线二进制运行环境),是高通公司推出CDMA网络上增值业务开发运行的基本平台。它提供一个高效、低成本、可扩展的应用程序执行环境(AEE), 着重开发可无缝植入任何实际手持设备的应用程序。Brew的面向对象可充分扩展的应用程序执行环境,允许使用C或C++开发游戏等小程序和共享模块。BREW应用市场前景非常看好,因此,我们有必要对基于BREW平台的无线应用开发中的若干难题进行研究,在本文中我们着重研究BREW手机游戏的内存管理技术。 2
手机内存的限制 与PC相比,手机的硬件平台有着明显的局限性。当前支持BREW的手机一般都是500KB到1000KB的可用堆内存,8KB到20KB的可用栈内存,还有一些大小不等的可以提供存放BREW程序的存储空间,这些都是非常有限的,如何利用这些有限的内存空间,就成了手机游戏的开发者应重点关注的问题。 手机中没有MMU,不能使用处理器的虚拟内存管理技术。手机采用的是实存储器的管理策略,因而对于内存的访问是直接的。它对地址的访问不需要经过MMU,而是直接送到地址线上,所有程序中访问的地址都是实际的物理地址。而且,对内存空间没有保护,各个进程实际上共享一个运行空间。一个进程执行前,系统必须为他分配足够的连续地址空间,然后全部载入主要的存储器的连续空间。 手机游戏的开发者必须考虑系统的内存管理。在设计开始,开发人员必须清楚这款手机到底拥有多少内存;在开发应用程序时,必须考虑内存的分配情况并明确应用程序需要运行空间的大小。另外,由于采用实存储管理的策略,用户程序同内核以及其他用户程序在一个地址空间,程序运行时要保证不侵犯其他程序的地址空间,以免破坏系统的正常工作,或导致其他程序的运行异常。因此,手机游戏的开发者对程序中的一些内存操作要格外谨慎。 3
受限内存常用的管理方式 在手机游戏的开发过程中,由于受内存的限制,一般采用以下管理方式。 (1)限制应用程序内存的使用量。为应用程序规定一个最大内存使用量,当超过此最大限制时,产生自定义的错误异常,不至于使整个应用程序乃至系统崩溃。 (2)使用纯数据文件的方式来存储常量数据。当应用程序需要使用这些数据时,为相应的结构分配内存空间并从数据文件中装载常量数据,使用完之后释放内存。这样避免了在应用程序启动时一次性将所有的常量数据装载于内存中,占据大量内存空间。资源文件的使用便是采用了此内存方式,即在使用之前,分配内存空间,通过文件I/O将所需要的数据从数据文件中读入;使用完成之后,立即释放内存空间。 (3)采用节约内存的数据打包方式。减少结构内每个字段所需要的内存量;减少字段之间闲置未用的内存。即使用能够满足需求的最小的数据类型;设计数据结构时考虑字段之间顺序的安排,避免空闲内存的产生。 4
常用的内存分配方式 下面介绍一些常用的内存分配方式。 (1)固定式分配:在初始化阶段为对象预先分配空间,这样可以精确估算出系统内存的使用情况。 (2)可变式分配:针对大小不定的对象,只有在需要的时候才分配。动态内存的管理需要额外的开销。 (3)内存抛弃:在暂态工作区中分配对象,用完便抛弃。 (4)池式分配:可以为大量的相似的对象预先分配一个对象池,循环使用其中未被使用的对象。 (5)引用计数:为每一个共享的对象保持一个引用计数,计数为0时便可以删除。BREW的每个接口对象都采用了引用计数机制。 (6)垃圾回收:辨识出那些不再被引用的对象,然后释放并归还相应的内存空间。JAVA和C#便采用了垃圾回收的机制。 5
BREW游戏内存管理 在RPG(Role Playing Game,角色扮演)游戏中,它的资源主要分为以下几个部分。 (1)全局资源:即在游戏的运行当中,随时都可能调用的资源。例如背包界面的图形资源。 (2)关卡资源:即只在该关中使用的资源,例如对话字符串、地图的图形数据等资源,这些资源在切换关卡的时候是必须要更换的。 (3)临时调用资源:保存程序运行当中的一些临时资源,用完之后立即释放。 (4)下载的资源:为了增加游戏的吸引力,必须增加动作的多样性。例如主角的装备可以更换,可以学习更多的功夫。但由于手机容量的限制,不可能把这些全部保存到手机上,因此需要动态下载。 我们根据RPG游戏所需资源的特点,设计了一种固定式分配与可变式分配相结合的内存分配与管理方式。它在很大程度上避免了内存的碎片。 第一步,计算游戏所需要的全部内存(需要动态下载的部分除外),将这些内存一次性分配成功。 第二步,将这些内存人为的给它分成三个部分:全局内存、关卡内存(类似堆内存)、临时内存(类似栈内存)。这三个部分由以下几个指针来管理:全局内存开始指针(m_pGlobal),当前全局内存指针(m_pGlobalCurrent);关卡内存的开始指针(m_pHeapStart);关卡内存的当前指针(m_pHeapCurrent);临时内存的开始指针(m_pStackStart);临时内存的当前指针(m_pStackCurrent)。它们的管理方式如下。 全局内存的使用:整块内存分配好之后,m_pGlobal、m_pGlobalCurrent、m_pHeapStart、m_pHeapCurrent均指向分配内存的开始,将整个游戏的全局资源调入内存,在调入过程中需要满足两个条件:一个是m_pGlobalCurrent<m_pStackCurrent,二是不能超过内存的结尾。在全局资源调入完成后,索定指针m_pGlobalCurrent,同时令m_pHeapStart=m_pGlobalCurrent。 关卡内存的管理:在调入全局资源后再调入关卡资源,此时须满足:m_pHeapCurrent< m_pStackCurrent。而在切换关卡时只需要将当前关卡内存指针复位即可,m_pHeapCurrent= m_pHeapStart。这样,在游戏切换关卡时对于内存的操作就十分方便。 临时内存管理:关卡内存分配完后即将临时内存的开始指针(m_pStackStart)和当前指针(m_pStackCurrent)指向内存尾部,需要分配内存时以栈的方式从后向前(从高到低)分配。条件:m_pStackCurrent>m_pHeapCurrent且m_pStackCurrent<m_pStack Start。临时内存释放时,令m_pStackCurrent=m_pStackStart。这样,对于临时内存的管理也很方便。 动态内存:何时下载何时分配,下载后将信息保存,在切换关卡时将内存释放。
图1 内存管理图 全局内存管理如图1所示。使用这种内存管理方法的优点是: ① 速度快,因为是一次性分配内存,避免了多次分配所花的时间; ② 不易产生内存碎片,避免频繁调用new/de1ete而导致内存碎片的产生; ③ 不容易产生内存泄漏,一般关卡内存中定义的变量生存期为一个1evel,进入下一个level前会清除,从而避免了忘记释放已分配内存的危险。 6
结束语 本文以BREW作为基本平台,研究手机游戏中的内存管理技术,针对RPG关卡游戏设计了一种新的内存管理方式,在游戏开发中有指导性作用。当然,这种内存管理方式还存在一些不足,应用不是很广泛,主要是在关卡游戏中比较实用。 (收稿日期:2007-07-06;Email:05120485@bjtu.edu.cn) |