Bruce Powel Douglass大师介绍-CSDN博客https://blog.csdn.net/ChatCoding/article/details/134665868嵌入式软件开发从小工到专家-CSDN博客https://blog.csdn.net/ChatCoding/article/details/135297955C嵌入式编程设计模式源码-CSDN博客https://blog.csdn.net/ChatCoding/article/details/134819019静态分配模式是一种内存管理策略仅适用于系统本质上静态的系统。内存池模式也是一种内存管理策略它在系统启动时预先分配一定数量的对象并在需要时提供给客户端使用。这种模式既避免了动态分配的非确定性和碎片化又提供了静态分配的灵活性适用于需要在运行期间分配和回收大量相似对象的系统。6.3.1 Abstract许多应用程序中大量的客户端可能需要创建对象例如数据对象或消息对象。这些对象的需求往往难以预测。这时预先创建对象池就很有意义此时没必要初始化对象。客户端可根据需要获取对象用完后归还池中。6.3.2 Problem内存池模式适用于以下系统系统需要频繁创建和销毁大量相似的小型对象例如事件、消息或数据对象。系统无法承受动态内存分配带来的问题例如内存碎片、性能开销和安全问题。系统无法预先静态分配所有对象例如由于系统过于复杂或对象的数量无法确定。具体来说内存池模式可以解决以下问题内存碎片内存池模式可以避免频繁创建和销毁对象造成的内存碎片从而提高内存利用率。性能开销内存池模式可以减少系统的性能开销例如减少垃圾回收的开销。安全问题内存池模式可以减少内存泄漏和越界访问等安全问题。6.3.3 Pattern Structure图 6-3 展示了内存池模式的结构。可参数化的泛型池管理器类用于创建特定类型的池化对象。系统中通常会存在多个这样的实例化池但每个特定的池化类型只有一个。每个池创建并管理其对象集在需要时分配对象并返回分配对象的引用或句柄给客户端。在释放后对象将被放回可用对象列表。6.3.4 Collaboration Roles客户端Client在嵌入式系统中任何需要使用resourceClass类的对象都是客户端。客户端通过调用ResourcePool::allocate()向池请求对象并在使用完成后通过ResourcePool::release()释放对象归还给池。通用池管理器Generic Pool Manager通用池管理器是一个模板类它使用模板参数pooledClass和BufferSize分别指定要池化的对象类型和数量。内存池PooledClassPooledClass 表示实例化类对象对所对应的存储空间内存池。它可以是任何你想要的对象但通常情况下它们是简单、小型的类由各种客户端使用。例如在嵌入式系统中PooledClass 可以是事件、消息、数据对象等。资源池管理器Resource Pool Manager资源池管理器类是已实例化的通用池管理器系统中可以有多个这样的实例但每个特定资源类最多只有一个实例。模板实例化是指为模板类或模板函数指定具体的类型的过程。6.3.5 Consequences优点:避免动态内存分配的复杂性:内存池模式在系统启动时一次性分配所有内存不需要动态分配内存。这消除了动态内存分配带来的诸多问题例如内存碎片、分配时间不确定性等从而提高了系统的稳定性和可预测性。适用于复杂系统:内存池模式可以处理一定程度的非确定性对象分配因此比静态分配模式更适合复杂系统。尤其适用于以下场景系统可能需要许多不同的客户端共享大量通用对象但这些对象的分配数量和分布无法在设计阶段确定。系统需要在运行时根据实际需求动态分配对象。提高性能:由于所有池化对象都在系统启动时创建不需要动态分配内存可以减少内存分配的操作从而提高系统的运行效率。缺点:对设计要求高:内存池模式要求在设计阶段确定所有池化对象的类型和数量。如果这种决策失误可能会导致系统在启动或运行过程中内存不足而崩溃。系统扩展受限:内存池模式的系统难以根据新的需求进行扩展因为池的大小在设计阶段就已确定。因此该模式更适合于需求明确、相对稳定的嵌入式系统。总结:内存池模式是一种有效的内存管理模式适用于需要频繁创建和销毁大量相似小型对象的嵌入式系统。在使用该模式时需要注意其对设计要求高、系统扩展受限等缺点并结合系统的实际需求进行权衡。6.3.6 Implementation Strategies本节提供了实现模式的策略特别是在C中。建议重写new和delete操作符以使用池管理器这可以隐藏应用程序程序员不必直接处理池化与动态分配的复杂性。内存池模式的实现相对简单。在 C 中为了方便使用通常会重写new和delete运算符使其直接调用池管理器进行分配和释放操作。这样应用程序开发人员无需关心是动态分配还是池化分配简化了代码。扩展与组合:内存池模式可以与其他设计模式组合使用例如与工厂模式[1]结合根据需要创建特定的子类型对象。具体实现参见《C高级编程》6.3.7 Related Patterns内存池模式与其他内存管理模式的关系静态分配模式:适用于相对简单的嵌入式系统所有内存分配都在系统启动时完成不需要动态分配优点是稳定可预测缺点是灵活性较低。动态分配模式及其变种:适用于更复杂的系统允许在运行时动态分配内存优点是更灵活适应需求变化缺点是容易产生内存碎片降低性能并带来内存泄漏风险。抽象工厂模式 [1] (Abstract Factory Pattern):可以与内存池模式结合使用在不同的运行环境中创建针对特定环境的池化对象提高代码的可重用性和灵活性。总结内存池模式是嵌入式系统中常用的内存管理技术适用于需要频繁创建和销毁大量相似小型对象的场景。选择合适的内存管理模式需要根据系统复杂性、性能需求和灵活性等因素进行权衡并考虑与其他模式的组合使用。6.3.8 Sample Model原书内容存在错误见红色对象模型 (图 6-4a):图 6-4a 展示了基于图 6-3 所示模式派生出来的类模型的对象关系。系统中存在一个TempDataPool对象管理着 1000 个TempData对象实例。图中还展示了三个TempDataPool的客户端TempSensor:每半秒记录一次温度的温度传感器。每次记录温度时TempSensor 会从池中分配一个TempData对象来存储温度信息。然后它将这个对象传递给两个客户端TempView 和 TempHistory。TempView 用于将温度显示在 GUI 界面上TempHistory 用于维护最近几秒钟的温度历史记录。TempView:一个 GUI 对象负责将温度值显示在用户界面上。当 TempView 显示完温度后它会释放之前从池中分配的TempData对象归还给池中。TempHistory:维护最近 10 秒钟的温度历史数据。对于前 20 个温度样本TempHistory 不会释放接收到的TempData对象而是将它们缓存起来。当收到新的温度数据时它会释放最老的TempData对象腾出空间存储新的数据。时序图 (图 6-4b):图 6-4b 演示了对象在运行期间的一个场景系统启动时首先创建TempDataPool对象并由它创建 1000 个TempData对象存储在池中。TempSensor 从池中分配一个TempData对象存储测得的温度值。TempSensor 将TempData对象分别传递给 TempView 。TempView 将温度值显示在 GUI 界面上。TempView 显示完温度后释放TempData对象将其放回池中。TempSensor 将TempData对象分别传递给 TempHistory。TempHistory 将TempData对象存储起来维护最近 10 秒钟的温度历史记录。对于前 20 个温度样本TempHistory 不会释放接收到的TempData对象。当收到第 21 个温度数据时TempHistory 会释放最老的TempData对象腾出空间存储新的数据。