为 C/C++ 项目构建您自己的内存管理器
Arpan Sen,*Synapti Computer Aided Design Pvt Ltd*, 被任命为该公司的技术领导
Rahul Kumar Kardam ( rahul@syncad.com), 高级软件工程师, Synapti Computer Aided Design Pvt Ltd
简介:
开始之前
了解本教程中包含的内容以及如何最好地利用本教程。
关于本教程
本教程基于基础方案为所有程序设计了一个统一的内存管理系统。该教程阐述了为何开发专门的内存管理系统对于提升程序性能至关重要,并详细说明了如何根据需求自定义内存管理系统的方法。
目标
在本教程中, 您将掌握设计内存管理器之前必须考虑的关键点, 运用一些具体技术手段来实现这一目标, 并且将在文章结尾详细讲解构建内存管理器的方法。您还将深入分析各种类型内存管理器的设计优缺点
跳转至页面顶端
先决条件
本教程旨在针对初级至中级水平的 Linux® 或 UNIX® 程序员。学习者应具备使用 UNIX 命令行 Shell 和 C/C++ 语言的基础知识。此外,在深入理解内存管理机制时,请掌握 malloc, calloc, free, memcpy 和 memset 这些系统调用的基本行为(它们负责内存分配、释放以及内容复制或初始化)。这些函数是实现高效程序设计的核心工具。
系统要求
为了能够执行本教程中的示例代码,
您必须配置了一套包含g++编译器工具链的Linux或UNIX系统环境才能运行。
此外,在内存方面也要求至少拥有约256 MB的可用内存空间
为什么要创建自定义的内存管理器呢?
为了提高代码运行速度的方法是什么?这与内存分配控制密切相关。为了深入理解内存管理机制的基础知识,请先复习C/C++语言中的动态内存分配相关函数。这些函数是C语言中进行动态内存分配的核心工具:标准库提供了malloc、free、calloc和realloc等四个接口用于实现动态空间管理功能。此外,在C++中通过new和delete等操作符实现了对动态对象的空间管理能力,请注意以下几点:
如像 malloc 和 new 这样的函数都具备内存管理的一般性。您的代码可能基于单线程设计,并且它所使用的内存管理部分同样能够支持多线程场景下的操作。然而,在这种情况下(即当程序运行多个线程时),其存在的直接后果就是性能有所下降了)。
当执行时
对于那些在程序运行期间被分配但随后不再需要使用的内存块而言,在C/C++语言环境中通常会忘记执行相应的清理操作。由于这些语言本身并不提供内置或自动化的垃圾回收机制,在未释放这些资源的情况下会导致系统对可用内存的需求不断增加。特别是在实际应用中的大规模系统中(例如多线程应用或网络服务器),这种现象的影响尤为显著)
设计目标
您的内存管理器应该满足下面的设计目标:
- 速度
- 健壮性
- 用户使用便利性
- 可移植性
速度
相较于编译器提供的分配器而言, 内存管理器的速度应更快. 频繁的内存释放和回收不应影响代码的执行速度. 尽可能地对内存管理器进行优化, 以便更好地处理代码中频繁出现的一些特定分配模式.
健壮性
在程序退出之前(即程序终止前),内存管理器应确保归还其向系统所申请的全部内存资源。这表明该系统设计旨在避免出现内存泄漏问题。此外,该机制还需要具备应对可能出现的异常情况(如请求过大的连续内存块)的能力,并提供有效的解决方案以应对这些异常。
用户使用便利性
当将其内存管理器整合到他们的代码中时, 用户只需进行少量的代码更改
可移植性
比较容易将内存管理器迁移至其他系统,并且必须避免的是与平台有关联的内存管理特性。
创建内存管理器的实用策略
在创建内存管理器时,下面的这些策略是很实用的:
- 发起大资源块的请求。
- 常见资源块的大小已经被优化。
- 在虚拟机环境中整合废弃资源。
请求较大的内存块
常见内存管理策略之一是,在程序启动阶段申请一些大量内存块;然后在代码运行期间反复使用它们。我们可以从这些内存块中划出部分内存来满足各种数据结构的需求;这将极大减少系统调用次数,并显著提升执行性能。
对常见的请求大小进行优化
在任何程序中,在一些特定的请求规模下出现频率较高的情况较为普遍。通过优化您的内存管理器以提高其处理能力,则能显著提升其运行效率。
在容器中收集删除的内存
在程序运行期间应将被删除的内存收集至容器中。随后应利用这些容器来处理后续的内存在线需求。若某次请求失败,则应将相关内存在线访问委派给预先在程序启动时分配的一个较大容量的空间。尽管最初目的是为了加快程序运行速度并防止溢出问题,但这种机制可能间接导致应用整体占用更少可用系统内存量。这是因为该机制能够有效地复用被移除后的系统资源。这也是自行构建一个有效的内存在线管理工具的重要原因之一!
分析 C++ new/delete 操作符的执行时间
让我们从一个简单的示例入手。假设您的代码中使用了一个名为 Complex 的类(该类用于表示复数)。这些操作符则提供了相应的功能机制。
例如,在清单 1 中所列述的技术细节,
清单 1. Complex 类的 C++ 代码
||
在每一次外层循环迭代中都会进行1,000次赋值与释放操作。经过5,000次这样的迭代后,系统将经历约一千万次用户与内核代码间的切换。当在Solaris 1_2_99上使用gcc-3_4_6进行源代码编译时,在运行测试程序时平均消耗约3秒时间。该测试程序用于评估现有全局new和delete操作符实现所带来的时间开销。为了优化现有内存管理系统的行为,请考虑重写Complex类中的特定new和delete操作符实现。
New/Delete:深入研究
在C++语言中,实现内存管理的组织实质上相当于对new或delete运算符进行重新定义。由于不同类可能具有各异别的内存管理需求,在这种情况下每个类都需要定制化的复制构造函数(即特定的operator new). 如果无法对全局运算符进行修改,则必须重新定义这些运算符(即重新编写全局的new或``delete```)。为此可以选择以下任一方案来实现运算符重载功能
清单 2. 重载 new 或者 delete 操作符
||
经过重写的 new 操作用于创建具有指定大小原始内存的对象。对应的 delete 操作将销毁该对象所占用的内存。请注意这些功能仅限于内存管理;它们不会自动调用构造函数或析构函数。对于通过 new 操作创建的对象而言,默认会调用其构造函数。只有在对象的析构函数被激活后才可能触发 delete 操作。
在C++语言中,“new”的第二种变体被称为'placement new'操作符。这种操作符要求接收一个特定类型的对象——MemoryManager。该数据结构主要用于为指定对象预留原始内存空间,并在构造函数之后完成初始化。为了简化代码设计并提高可读性,在本教程中推荐优先使用'new'或'delete'的第一种形式。
为了实现将 new 和 delete 操作符例程用作下面某个 MemoryManager 实例程序包的目的,并完成对内存的实际分配或回收工作,请参考清单 3,其中定义了一个全局变量:gMemoryManager(全局内存管理器)。
清单 3. 作为包装的 new、new[ ]、delete 和 delete[ ] 操作符
||
注意:
- 由
new[ ]操作符传递过来的长度等于数组每个元素的大小与数组元素个数相乘的结果。 - 这个指针并不是在任何类特定的操作符(如
new、delete、new[ ]或delete[ ].)中都可以使用的。实际上,在设计过程中必须始终记住这些操作符的作用范围。 - 除了通过全局变量声明内存管理器外,在设计过程中还可以采用单例模式。
在目前的介绍中提到,在清单4中详细列出了内存管理器类的核心功能模块
清单 4. 内存管理器接口
||
我们还倾向于将 allocate 和 free 例程充当内联例程,并且是为了实现更为高效的分发过程。
单线程环境中 Complex 类型的第一个内存管理器
我们开发了本教程的第一个内存管理器,并始终铭记至今所介绍的各种原则。鉴于简单性的考虑,该自定义内存管理器专为处理Complex类对象而设计,并且仅限于单线环境运行。该内存管理系统的基本功能是在可访问的有效内存管理器中维护一个Complex对象池,并通过此池来完成后续资源分配任务。当需要创建的新Complex对象数量超过现有对象池中的数量时,则对该对象池进行扩展。被删除的对象将被返还至该对象池。图1很好地说明了所发生的事件
图 1. 创建 Complex 对象的池

该池中的每个块具有两个用途:
- 它保存了一个 Complex 对象实例。
- 该机制确保其能够与池中的后续组件建立关联。
未在 Complex 数据结构中存储一个指针,因为这种方式会增加内存空间的总体占用。相比之下,则建议将 Complex 数据结构的私有变量封装到一个新的结构中,并将其与 Complex 指针结合在一起创建复合体。作为池的一部分使用时,请通过这个指针可以找到下一个可用的空间位置。而当作为独立的 Complex 对象使用时,则可以利用该复合体来分别存储实数和复数部分。参考清单 5(http://www.ibm.com/developerworks/cn/education/aix/au-memorymanager/section7.html#list5)展示了这种方法的具体实现效果。
列表项5. 调整优化后的数据架构,在无需额外消耗资源地存储 Complex*
||
清单 6
清单 6
清单 6. FreeStore 对象的数据结构
||
之后
清单 7. 经过修改的 Complex 类数据结构,其中提供了 FreeStore 功能
||
下面是用于内存分配的伪代码:
- 若未预先创建可用空间,则先建立可用空间之后直接转移至步骤3。
- 当现有可用空间已用尽时,则生成一个新的可用区域。
- 获取该区域中的第一个对象,并使该对象后面的记录暂时不可用。
下面是用于内存删除的伪代码:
- 将删除指针中的 next 域设置为当前空闲存储的第一个节点。
- 将删除指针设置为空闲存储的第一个节点。
[清单 8] 包含了 Complex 类的 new 和 delete 运算符的源码。[清单 9] 展述了闲置存储的扩展与清理机制。目前问题依然存在。您是否能够具体指出存在的问题?
清单 8. 用于 Complex 类的自定义内存分配或者释放
||
空闲存储的创建并非易事。其核心在于认识到同一个FreeStore*指针不仅能够表示一种数据类型(如FreeStore),还可以被用来表示另一种更为复杂的对象(如Complex)。因此,在为单个FreeStore指针分配内存时,其所需空间应基于FreeStore*或Complex对象中较大的那个尺寸(参考清单9)。
清单 9. 扩展或者清空空闲存储的代码
||
有趣的说明
仍然使用整体 new 和 delete 操作符生成空闲内存块。此外,您还可以利用 malloc 和 free 的搭配来实现内存管理。这两种方法在执行效率上差异不大。
大获全胜!您已成功开发出专为 Complex 类量身定制的内存管理系统。
编译后运行相同的测试程序时,请注意无需在主例程中修改客户端代码即可完成编译及运行操作。
请问为何该系统展现出如此明显的性能优化?
主要原因在于采用了基于现代缓存友好设计的新算法;另一个关键因素则是引入了一种高效的多线程同步机制。
- 在用户与内核代码之间的交换次数大幅下降,其主要得益于系统通过将删除的内存收集回空闲存储来重用这些内存.
- 该内存管理器专为单线程环境设计.该系统排除了多线程场景的可能性.
在对话中询问您是否发现了设计中的问题时,请您注意以下关键点:首先,在这种设计中若未删除通过new操作符创建的Complex对象,则无法实现内存回收目标;同样地,在编译器提供的new和delete全局操作符被开发人员采用的情况下也会面临同样的挑战;然而,在内存管理方面不仅关注性能优化还需预防内存泄漏的发生;对于那些手动创建并通过new操作符生成的Complex对象需要执行显式的memory delete操作才能使cleanUp例程正常工作;目前的cleanUp机制仅能将内存资源返还给操作系统;为了解决这一问题建议在程序初始化阶段请求操作系统提供更大的内存块并对这些块进行集中管理;在此基础上开发一种机制能够在这些内存块中预留足够的空间以满足动态需求;最终目标是在cleanUp例程运行时将其作为一个整体释放而不是从各个独立的对象中处理
位图内存管理器
基于最初设计好的固定容量内存分配机制的基础上, 我们可以实现一种有趣且高效的位图式内存管理系统。系统向操作层面提交较大的连续内存块请求, 并在这些块中预留一部分用于动态分配, 在释放操作中将每个块视为独立的整体, 从而避免任何潜在的泄漏问题。这种机制还具备支持数组形式的新对象和旧对象删除操作的能力。
在该方法中, 内存管理器会要求较大的连续段. 然后将其分割成若干固定大小的小段, 每个小段占用的空间等于单个 Complex 对象所需的空间. 基于这些小段的数量建立一个比特图(BitMap), 该比特图用于指示各个小段的状态(空闲或被占用), 并且比特的数量与小段的数量一致. 当程序申请新的 Complex 对象时, 内存管理器会通过检查比特图找到第一个可用的小段. 对于所有未被占用的小段时间, 将其对应的位置设为1; 而已被占用的时间则设其对应的位置为0. 同时需要维护额外的数据结构, 以便在创建或销毁 Complex 数组对象时帮助统计比特图中有多少位置应置1或置0
创建一个位图内存管理器
该内存管理器向操作系统发出请求以获取足够大的一块连续的物理地址空间。操作系统的这块空间会被划分为一个较大的虚拟分区用于后续资源分配。当无法获得所需内存时系统会尝试重新规划资源并将其适当信息传达给用户告知其已关闭状态在这一阶段内位图中的所有记录都被标记为1的状态
当内存在耗尽空闲内存块时,则会继续向操作系统申请更大容量的空间。在MemoryManager数据结构中设置了多个位图以分别匹配相应的物理空间资源。然而,在执行删除操作后,在这些被释放的空间中可能会出现断片状态,并从该内存中获取相应大小的空间以满足后续需求。
清单 10 中给出了 MemoryManager 类的基本结构。它包含 MemoryPoolList,后者保存了从操作系统中请求的内存块的起始地址。对于每个块,在 BitMapEntryList 中都存在一个相应的条目。FreeMapEntries 是一种数据结构,可以用来为 new 调用的非数组版本提高下一个可用空闲块的搜索速度。
清单 10. MemoryManager 类的定义
||
ArrayMemoryList记录了为Complex对象数组占用内存的情况信息。其本质是从起始地址到结构的一种映射关系, 用于管理MemPoolListIndex、位图中的起始位置以及该类别的数据长度等参数。
清单 11. ArrayInfo 结构定义
||
为简化对位图的操作, 可将该 BitMapEntry 对象用作存储某些额外元数据信息的地方, 并参考清单 12 的内容. 设置一个或多个位时可使用 SetBit 和 SetMultipleBits 程序接口. FirstFreeBlock() 程序接口用于检索该位图指向的第一个空闲块.
清单 12. BitMapEntry 类定义
||
该内存管理器初始化了一个大小为n的位图数组。该数组中的每一位代表一段特定的内存块,并且所有记录字段被设置为1。这些初始化操作由BitMapEntry类的构造函数执行。
当调用 Complex 类的对象初始化函数(即 new)或动态内存分配函数(即 malloc)时,在这些非数组版本的情况下,请注意以下步骤:系统会首先检查 FreeMapEntries 结构体中的可用内存区域。如果发现至少一个可利用的空间,则立即释放该空间;否则系统会申请新的内存空间,并记录相应的位图信息。接着,在获取到合适的资源后,请确保将这部分空间分配给当前操作需求;最后,请确保将其标记为不可用的状态,并传递回相应的地址。清单13 中展示了相关代码。
清单 13. MemoryManager::allocate 定义
||
清单 14 包括为单个块设定或重置位的代码实例
清单 14. MemoryManager::SetBlockBit 定义
||
清单 15 提供了为多个块赋值或重置位的具体实现
清单 15. MemoryManager::SetMultipleBlockBit 定义
||
在处理数组版本时采用了不同的方法。其相比于单个对象使用独立分配的方式,在实现上有所不同:其内核采用了一种全新的机制来进行资源管理与优化配置,在性能上有显著提升的同时也降低了资源浪费的问题出现频率。此外,在寻址策略上也进行了相应优化:当遇到特定场景时系统会自动切换到更适合当前任务模式的操作流程路径,在一定程度上提升了整体系统的运行效率和稳定性表现
在使用指向 Complex 类型对象的指针调用 delete 或 free(非数组版本)的过程中,请首先确定包含该指针的内存区域(参考清单 16)。随后通过该内存区域对应的 BitMapEntry 设置相应的位为 1 以释放该区域。整个过程的时间复杂度为 O(1)。当处理 delete [] 操作时,请从 ArrayMemoryList 中获取相关信息,并根据已知起始位置和位图大小将相应区域标记为可用。
清单 16. MemoryManager::free 定义
||
在下载的部分中,附带提供了一份完整的位图内存管理器代码清单。该份清单作为本节讨论内容的一个实践案例,并包含了我们在本节所涉及的所有相关资源。
在下载的部分中, 包括了一份完整的位图内存管理器代码. 这份代码作为本节讨论内容的一个实践案例, 并包含了我们在本节所涉及的所有相关资源.
继承带来的问题
派生类的大小往往会与其基类显著不同。例如说,在 Complex 类的基础上创建一个派生变体 ComplexT 是一种合理的选择方案。这种派生变体专门用于记录复数值随着时间变化而发生的变化情况,并且包含了额外的一个 unsigned long 来记录时间信息。值得注意的是,在这种情况下原先经过重写的 new 或 delete 操作符已经失效了(除非我们特别为该派生变体重新定义这些操作符)。对于这一问题而言共有三种可能的解决办法:
- 采用MemoryManager分别为这两个不同的类维护各自的内存池。具体而言,在这种机制下涉及分配与回收机制的不同实现,并同时管理着表示这两个内存块起始位置的指针变量。
- 基于最大子类规模设计内存管理方案:其中核心函数负责获取所需内存的空间块,并将其分配给相应的对象实例;然而该方法虽然解决了资源分配问题但它并非最优选择因为会导致程序整体占用过多系统资源。
- 开发一种适用于不同对象大小需求的一般化内存管理框架。
基于空闲列表的内存管理器
在一个常规程序中, 内存块中的多数请求均为固定容量。
有关保护字节(guard bytes)的简单介绍
n个字节组成的数据块不仅承载了原始对象信息,还附加了若干元数据字段以供后续处理。在每个数据块末尾附近设置了四个特定字节,这些字段通常用于记录操作边界信息以及错误修复相关参数。一般而言,当调用memcpy或memset函数时,程序可能会超出预先分配内存空间范围进行读写操作,这可能导致堆溢出问题的发生。现代编译器在分配内存时通常会附加一些特定标记,这些标记主要用于标识内存区域边界及其相关的安全保护层。对这些内存块的所有操作行为都会被严格监控,只有当相关区域内的特定标志存在时,系统方能确认该区域处于有效状态;如果标志缺失或损坏,则视为该区域可能被非法修改过,从而导致系统的整体稳定性受到影响。通过这种方式,程序能够及时发现并修复一些潜在的安全漏洞;以下实例详细说明了这组保护字段的具体作用机制:其中第一个字段主要作为保护字节功能实现载体,第二个字段用于存储对象占用空间大小数值信息,第三个字段则配置了一个二进制位来标识当前对象是否被其他进程占用或正在使用中状态;最后一个字段则作为一个可读性控制位,其值决定了程序是否允许对该对象进行进一步的操作或查看操作结果等信息。
创建一个空闲列表内存管理器
正如前述所述,在系统运行期间, 管理器负责监控一组动态变化的数据结构, 包括多个独立的数据块以及来自操作系统分配的空间资源. 此外, 在接收操作系统分配的内存块时, 它会将其标记为一个专用存储池(memoryPool)。当A对象在其析构函数被调用时, 该机制会自动释放所有相关资源. 清单 17 提供了这一数据模型的具体实现方案
清单 17. 基于空闲列表实现的 MemoryManager 类定义
||
我们采用了大小分别为16、28和32字节的三类数据结构来表示内存块,并因此要求为这些数据块分配容量分别为24、32和40字节的空间以存储保护字节。由此可见,在当前代码中对容量为24、32和40字节的数据指针列表的需求最为突出,并且处理相关操作主要集中在这些指针列表上。尽管如此,该系统的设计方案具有极强的可扩展性特征,在未来也可以轻松地支持其他不同容量的数据指针列表类型。
对于某些特定类型实现了相应的构造函数(即对这些类实现了相应的构造函数),这些操作符(即new和delete)将委托给负责内存管理的相应例程(即将调用委派给负责内存分配和释放的任务)。本节将详细介绍这些关键操作符的具体实现细节。具体来说,在实现过程中采用了固定大小为1024的数据块作为对象的基本计数单位(即对象的基本计数单位)。此外,在存储结构中,默认设置了与示例中所使用的各个数据类型的预定义大小参数。
这些参数包括:
- 清单 18 中所列的具体数值设置。
通过这种方式实现了对内存资源的有效管理。
清单 18. 这个实现中所使用的预定义常数
||
在 allocate 和 free 例程中使用了这些常数。
allocate 例程
当处理大小相近的一组数据时,在内存管理过程中程序会自动选择一个合适的区域来存放这些数据。具体来说,在内存管理器中指定的位置会有专门用于存储这些数据的相关信息和属性值。需要注意的是,在这种情况下生成的数据结构仅包含一些简单的属性值,并不包含复杂的数据对象(这些对象都是属于同一个记忆体区块的一部分)。
当空闲列表为空时,操作系统会要求添加额外的内存块,并由这些例程负责将其组织成分区块。
当发现某一个空闲可用内存块时,在系统中将其标记为不可再利用的状态,并设置相应的保护位;然后系统会自动记录下该内存块的位置信息,并返回该内存块的起始地址位置。需要注意的是,在实际应用中可以选择参考清单 19中的具体实现方案以确保系统的稳定运行。
清单 19. MemoryManager::allocate 定义
||
free 例程
该例程接收指定内存块的起始地址,并在其末尾处查找包含大小信息且受保护的数据字节。这些数据单元位于内存块的最后一对连续位置中的前一个位置。确定了数据长度后,在内存空间中释放对应的数据区域,并将其标记为可回收资源。将这些可回收资源记录到空闲资源列表中并表示内存释放过程完成。参考相关技术文档中的详细描述以获取更深入的理解和实现细节。
清单 20. MemoryManager::free 定义
||
在该链接中包含了空闲列表内存管理器代码的完整清单。该资源包含了一个实现空闲列表内存管理器的工作示例,并涵盖了我们在本节中讨论的所有相关内容。
优点和不足之处
这个设计有下面几个优点:
- 支持灵活管理内存空间并能有效应对不同内存规模的需求。
- 该系统设计具有高度灵活性,并能在预设列表规模下实现动态扩展。
- 系统新增了对数据进行加密保护的功能模块,并提供了相应的安全配置接口。
此外,在实际应用中我们已经成功实现了基于此功能模块的安全性测试,
并验证了其在保障系统安全性的有效性。
尽管这一方案能够明显地提升性能水平,然而它仍存在一定的缺陷,具体表现为其对内存资源的消耗极为巨大.
多线程内存管理器
到目前为止,我们所构建的内存管理器尚未充分考虑多线程环境的影响。当多个线程同时运行时,在内存分配和释放方面可能存在竞争。因此,在设计内存管理器时必须确保所有分配与释放操作均采用原子操作。也就是说,在两个线程同时试图执行这些操作时,则必须为这两个线程提供互斥机制。为了实现这一点,则必须使用基于锁机制的方式来保证这些操作具有原子性。具体而言,在一个线程调用相关方法之前必须获得对相应资源的独占访问权;如果该锁由另一个线程持有,则当前线程将被阻塞直至其获得该锁为止。清单21(见参考链接)详细列出了用于实现锁定机制的相关函数签名
清单 21. pthread mutex 方法
||
在本文中, 我们采用了基于标准库文件名...定义的Pthread互斥锁. 由于编译器预置了该包含头文件, 因此无需额外配置即可直接使用. 其相关函数体位于对应互斥锁和互锁存方法之间. 当一个线程正在访问内存池时, 另一个线程可能调用了其中任何一个函数, 则该线程需等待直至相应的互斥操作完成. 这样的机制有助于防止资源竞争问题. [清单 22]链接至IBM Watson Studio中的相关技术文档, 提供了该方案的具体实现细节.
清单 22. 分配和释放方法的并发版本
||
当前阶段需配置内存管理器类中应包含一个 pthread_mutex_lock 实例。为了确保线程安全,在初始化阶段需使用 pthread_mutex_init 进行锁初始化;同时,在析构阶段需确保正确释放资源并调用 pthread_mutex_destroy 灭绝 lock 对象。参考链接 清单 23 提供了更新后的 MemoryManager 类代码。
清单 23. 经过修改的 MemoryManager 类,以处理多线程的分配和释放
||
该多线程内存管理器正在运行中,在我们的测试中发现其运行速度较慢。这一现象表明为特定需求开发专用化内存管理器是必要的
总结
本教程解释了下面的几个概念:
- 用户代码中对内存管理器的应用需求。
- 设计内存管理器所需的关键要素。
- 详细说明如何构建固定大小的分配器或内存管理体。
- 探讨动态资源分配方案的具体方法。
- 分析多线程环境中资源优化配置的重点。
关于这一主题的相关信息,请参考参考资料一节。
下载
| 描述 | 名字 | 大小 | 下载方法 |
|---|---|---|---|
| Source files for bitmapped memory manager | bitmapped_memory_manager.zip | 4KB | HTTP |
| Source files for free-lists based memory manager | free_list_mem_mgr.zip | 3KB | HTTP |
该文档旨在提供关于信息获取途径的选择与评估
参考资料
学习
- 内存管理参考资料:该 Ravenbrook的Web 站点介绍了内存管理的相关知识。
*内存管理机制”(Doug Lea):该资源详细阐述了一系列相关技术和算法策略。
-
“内存管理内幕”:这篇文章提供了有关内存管理技术的概述,Linux 程序员可以充分地利用这些技术。
-
IBM developerWorks 专家网络平台——AIX and UNIX 专区:该平台的“AIX and UNIX 专区”汇聚了丰富的与 AIX 系统管理各个方面相关的信息资源,通过它们提升自己将能够更好地掌握 UNIX 技能。
-
IBM AIX/Linux_UNIX 新手指南:访问相关页面获取详细信息.
IBM开发 works电子资料库:通过该平台访问电子资料库,并查找相关技术资料。
- IBM 开发者Works 技术活动和在线直播:了解最新的 IBM 开发者Works 技术活动和在线直播。
获得产品和技术
- IBM官方提供试用软件包:您可以从 IBM 开发者Works网站直接获取这些试用软件包,并通过该平台获取相关文档支持
讨论
请注册并访问developerWorks Blog以便成功加入到developerWorks 社区中来
作者简介

Arpan 是一位专注于电子设计自动化领域的软件开发首席工程师。他在 Solaris、SunOS、HP-UX、IRIX 等多种 UNIX 版本以及 Linux 和微软 Windows 系统上进行了长时间的开发工作。Arpan 对软件性能优化技术、图形理论以及并行计算充满浓厚兴趣。编写技术文章使 Arpan 感到极大的成就感。另外值得一提的是,Arpan 还获得了软件系统方面的硕士学位。
Rahul Kardam 是一名资深软件工程师,在复杂电子设计自动化领域有着深厚的造诣。特别在利用 C++ 开发复杂且精密的电子系统时展现出卓越的专业能力。经过大量实践,在 Windows 和 UNIX 操作系统平台间积累了丰富的实践经验。他对开源社区充满热情,并将其作为构建自己使用的可靠且可扩展自动化工具的基础框架平台。
