背景
在内存受限设备中,经常会遇到这样的问题:
如何在多个相互竞争的组件之间分配内存?
例如,在一部普通的手机中,有游戏、音乐播放、图形界面等组件,每个组件对内存的需求都是“贪婪”的,并且这种“贪婪”是有道理的,即一般情况下,组件得到越多的内存,则该组件的运行表现越良好。但是如果放任每一个组件都去试图尽量多地分配内存,那么系统的总内存将入不敷出。
让我们撇开数量众多的嵌入式设备不说。即便面对如今内存动辄上G的智能手机,我们依然应当谨慎地为各个组件分配内存。
模式
让我们考虑如下的模式:
为每个组件设置限额,超过限额的请求将不予响应。
我们将它称之为:内存限额。
内存限额的目标是防止某一个组件独霸内存。
更深入的探讨
现在,你也许会有这样的疑问,如何确定每个组件的内存限额?
首先需要明确的是,内存限额模式对于内存需求有变化的组件才有意义,如C++中的vector,java中的arraylist。
内存限额的分配应当遵循“小富即安”的原则,即限额应当确保该组件的正常运行即可。有一点原则必须明确:即便某一个组件运行性能特别出色,其他组件也可能成为整个系统性能的瓶颈。内存和CPU的故事,想必无需我再赘述。
适用的场景
警觉的朋友会对这个模式产生疑问。是的,这个模式是一个容易浪费系统内存的模式。即便系统中有空闲内存,某一个组件也可能因为自身的限额而失败。
这个模式适用于负荷稳定、几乎没有弹性负荷的场景,实现简单是它的最大优点。
实现
终于可以脱离纸上谈兵了(*^__^*)
有以下几种方法可供选择,以实现该模式。
- 重写内存管理函数。比如,你可以重写c++中的new和delete方法。
- 分离的heap。可以让每个组件各自使用分离的heap。windows系统的操作系统支持该操作,至少我知道的,windows CE是肯定支持的。
- 分离的进程。大部分的linux允许开发者为每一个进程指定一个内存限额。很方便,不是吗?
示例
下面的C++代码限制MemoryRestrictedClass及其子类所使用的内存总量。如果超额分配,会触发内存不足异常。
class MemoryRestrictedClass{
public:
enum { LIMIT_IN_BYTES = 10000 };
static size_t totalMemoryCount;
void* operator new(size_t aSize);
void* operator delete{void* anItem, size_t aSize};
};
size_t MemoryRestrictedClass::totalMemoryCount = 0;
// 实现new操作符
void* MemoryRestrictedClass::operator new(size_t aSize){
// 如果分配后内存大于限额,抛出内存不足异常
if ( totalMemoryCount + aSize > LIMIT_IN_BYTES )
throw (bad_alloc());
// 更新计数器,增加之
totalMemoryCount += aSize;
return malloc(aSize);
}
// 实现delete操作符
void* MemoryRestrictedClass::operator delete(void* anItem, size_t aSize){
// 更新计数器,减少之
totalMemoryCount -= aSize;
free((char*)anItem);
}
下面来看看相对不那么“强大”的java语言如何实现内存限额模式。
是的,java没有提供内存分配和销毁函数,然而限制某一个类的实例数量还是可以做到的,只需要提供一个static的计数器即可。
问题又来了,java如何获取占用内存已被归还?我们可以使用finalize()函数来拦截这一动作,然而,大多数java虚拟机finalize的效率不佳,因此,以下代码仅仅是一个示范,绝非推荐做法(具体请参看Gosling所著的《java语言规范》一书)。
Class RestrictedClass{
// 最大可分配10个实例
static final int maxNumberOfInstances = 10;
// 伟大的计数器又出现了
static int numberOfInstances = 0;
public RestrictedClass(){
numberOfInstances++;
if ( numberOfInstances > maxNumberOfInstances ){
// 出师未捷身先死,直接被回收掉...
System.gc();
throw new OutOfMemoryException("只能创建10个对象");
}
}
public void finalize(){
--numberOfInstances;
}
}
预告
下一篇,介绍小型接口。
分享到:
相关推荐
总的来说,《内存受限系统之软件开发》这本书提供了丰富的理论知识和实践经验,帮助开发者掌握在有限资源下设计和实现高效软件的关键技能。无论是嵌入式系统的开发,还是物联网设备的应用,甚至是移动设备的软件设计...
### 内存受限系统开发——《ThinkinSmall》:用户参与技术处理UI中的内存限制 #### 概述 本文档探讨了在有限内存环境中开发软件时的一些关键问题和设计模式,尤其是在用户界面(UI)的设计方面。对于那些需要运行...
装饰模式是一种设计模式...通过阅读和理解《设计模式:可复用面向对象软件的基础》等经典书籍,以及像博客“设计模式——装饰模式”这样的在线资源,我们可以深入掌握并灵活运用装饰模式,提高代码的可维护性和扩展性。
适配器模式是一种软件设计模式,它允许两个不兼容的接口之间进行通信。在软件工程中,当系统中存在已有的类或组件,但其接口不符合当前系统需求时,适配器模式能起到桥梁的作用,使得旧的组件可以无缝地与新系统协作...
### 内存受限系统软件开发中的UI设计模式与思考小型化方法 #### 一、引言 在现代软件开发过程中,特别是在嵌入式系统或移动设备等资源受限环境中,如何有效地利用有限的内存资源成为了一个重要的挑战。《内存受限...
为了更好地理解和分析当前农业电子商务的营销模式,毕慧芳、黄颖所著《农村电商新思维——农业创新营销模式设计》一书详细介绍了“互联网+”农业营销的核心理念、农产品打造之路、品牌农业的发展、农业创新营销策略...
### Android内核驱动——内存...通过上述解析,我们可以看到LowMemoryKiller在Android内核中的重要地位及其精妙的设计思路,它不仅有效地缓解了内存压力,也为Android设备在资源受限环境下的稳定运行提供了有力保障。
资源就越多,从而导致消耗更多的内存资源。如果某个设计中所选的MCU没有足够的片内 Flash和片内RAM来存储图像和字体,那么就不得不使用片外Flash和片外RAM。 幸运的是,LVGL提供了文件系统机制来支持外部存储设备,...
通过理解内存泄露的原因,运用恰当的设计模式和编程技巧,同时借助工具来监控和分析内存使用情况,可以有效地提升应用的性能,延长应用的生命周期,避免因为内存问题导致的崩溃,提升用户的使用体验。
直销模式下,企业直接面向消费者或零售商,减少了中间环节,提高了反应速度和服务质量,但同时也受限于交通条件和人力物力的投入,可能在某些区域存在销售盲点。 其次,网络式销售适用于大众化产品,娃哈哈和康师傅...
斯凯MRP源码——拓展内存使用示例 在IT行业中,特别是在嵌入式系统或者资源有限的设备上,内存管理...通过学习这些内容,开发者可以更好地应对内存受限环境下的软件开发挑战,提升系统性能,从而优化企业的资源管理。
### 高级语言程序设计的精髓——算法设计 #### 概述 计算机程序设计语言作为人与计算机交流的重要工具,在计算机科学领域扮演着至关重要的角色。随着计算机技术的飞速发展,程序设计语言经历了从机器语言、汇编...
适用于有限存储系统(即手持式和专用微型计算设备)的一组连贯且易于使用的模式。 包括C ++和Java中的示例。
选项C错误,因为虚拟内存的大小受限于物理内存和磁盘空间的总和。 3. **分区分配内存管理**:分区分配是早期操作系统常用的内存管理方式,其中界地址保护用于防止进程超出其分配的内存区域。选项B、C和D都不是分区...
本例程“C嵌入式编程设计模式例程-1”聚焦于如何在资源受限的嵌入式环境中有效地应用设计模式。下面将详细介绍与这些标签相关的知识点。 首先,C语言是嵌入式系统中最常用的语言之一,其简洁、高效和低级别的特性使...
书中还会讨论如何在资源受限的环境下优化这些模式,包括内存管理、效率优化和实时性考虑等方面。此外,作者可能还会介绍如何在C语言中实现面向对象的一些技巧,如模拟继承和多态,以及如何通过封装和模块化来提高...
以上介绍了Oracle 12c中四种特殊的运行模式——受限模式、只读模式、静默模式和延迟模式。这些模式各有其独特的用途,可以帮助DBA们更高效、安全地管理数据库。理解并熟练掌握这些模式对于日常的数据库管理和维护...
标题“基于IP理念的农产品电商平台模式探索——以长泰县为例.pdf”涉及的是利用知识产权(IP)理念对农产品电商平台的模式进行创新性探索,具体以中国福建省长泰县作为研究案例。该研究不仅分析了当前农产品电商的...