当前位置: 首页 > news >正文

6.2 静态内存分配模式

Bruce Powel Douglass大师介绍-CSDN博客https://blog.csdn.net/ChatCoding/article/details/134665868

嵌入式软件开发从小工到专家-CSDN博客https://blog.csdn.net/ChatCoding/article/details/135297955

C嵌入式编程设计模式源码-CSDN博客https://blog.csdn.net/ChatCoding/article/details/134819019

静态分配模式只适用于负载(内存量)高度可预测且稳定的简单系统。在适用的情况下,使用这种模式可以使系统易于设计和维护。

6.2.1 摘要

动态内存分配在实时嵌入式系统中存在两个主要问题:

  • 内存分配和释放的时间不确定。
  • 内存碎片化。

这种模式采用了一种非常简单的方法来解决这两个问题:禁止动态内存分配。这意味着所有对象都在系统初始化期间分配。如果设计时能够知道内存负载,并且能够为最坏情况分配足够的内存,那么系统虽然初始化时间会长一点,但运行时将更加稳定高效。

6.2.2 问题

动态内存分配在结构化和面向对象设计中非常普遍。例如,C++ 语言使用newdelete来分配和释放内存,C 语言则使用mallocfree。在这些语言中,程序员都需要显式执行这些操作,但也很难想象任何大型程序不使用分配内存的指针。而 Java 语言更加彻底,所有对象都存放在动态内存中,这意味着所有对象创建都隐式地使用了动态内存分配。此外,Java 还会在内存不再使用时自动释放它,但具体何时何地发生则不在程序员的控制范围内。

尽管很常见,动态内存分配始终是让实时系统开发疼痛的问题,主要有以下三个难题:

  • 非确定性:动态内存分配和释放的时机通常是不可预测的,因为这通常需要搜索数据结构以找到可分配的空闲内存。这会导致系统的行为难以预测,甚至出现不可预料的延迟或中断。
  • 内存泄漏:如果程序员没有正确释放不再使用的内存,就会发生内存泄漏。这会导致系统内存的逐渐减少,最终导致系统崩溃。
  • 内存碎片化:由于内存是以不同大小的块分配的,释放顺序通常与分配顺序无关。这会导致空闲内存出现碎片化,即无法找到足够大的连续空闲内存块来满足新的内存请求。

上述三个难题都可能导致实时系统出现严重的性能问题或甚至崩溃。因此,在实时系统中,应尽量避免使用动态内存分配。

6.2.3 模式结构

图 6-1 展示了该模式的基本结构。它结构非常简单,但可以通过嵌套抽象层来处理任意大小的系统。系统对象启动初始化过程,并创建最高级别的复合对象。这些复合对象通过组合关系连接到其他复合对象或原始对象。原始对象被定义为不会动态创建其他对象的类。使用组合关系是因为它们清晰地标识了创建/删除的责任。

6.2.4 协作角色

  • Allocation Plan(分配计划):如果存在,标识最大系统复合对象应该按照哪个顺序分配。
  • Composite Object(复合对象):复合对象通过组合关系负责创建它所拥有的所有对象。

分配计划

分配计划(Allocation Plan)是可选的,用于指定最大系统复合对象的分配顺序。如果没有分配计划,则系统可以按任何所需的顺序分配对象。

复合对象

复合对象(Composite Object)是指与其他对象之间存在组合关系的对象,其他对象可以是复合对象或原始对象。复合对象负责通过组合创建它所拥有的所有对象。复合对象和系统对象都不能释放内存。

复合对象可以由其他复合对象组成,但每个通过组合关系拥有的对象只能属于一个复合对象。这意味着模式中清楚地标识了系统中每个对象的创建责任。

部件对象

部件对象(Part Object)是复合对象和原始对象的父类。它允许系统对象和复合对象通过组合包含复合对象和原始对象。

原始对象

原始对象(Primitive Object)是指不负责分配任何其他对象的类。所有原始对象由复合对象创建。

系统对象

系统对象(System Object)是系统中最高抽象层级的对象。它的职责是通过创建和初始化系统的主要部分(最高级别的复合对象)来“启动”系统。这些复合对象又会创建自己的部分,依此类推。一旦所有对象都创建完毕,系统对象就会通过运行begin操作启动系统执行。

6.2.5 结果

静态分配模式将所有对象都在系统启动时进行内存分配,适用于以下情况:

  1. 最坏情况可预测且内存充裕:系统的峰值内存需求是已知且可控的,并且拥有足够的内存满足这种情况。
  2. 内存负载稳定:系统在不同运行状况下的内存需求差异不大,保持相对稳定的内存占用。
  3. 系统规模较小:需要预先分配所有对象内存的特点限制了系统规模,适合用于较小的系统。
  4. 对内存成本不敏感:系统对内存成本相对不敏感,预先分配内存造成的潜在浪费可以承受。

使用静态分配模式的系统拥有以下优势:

  • 更快的运行速度:启动后执行代码无须进行动态内存分配,运行速度通常比动态分配更快,有时显著更快。
  • 更可预测的执行:消除了动态分配带来的非确定性因素,使系统运行更加可预测。
  • 无内存碎片化:不进行内存释放,就不会出现内存碎片化的问题。

然而,静态分配模式也存在一定的缺点:

  • 启动时间较长:需分配所有对象内存,导致启动时间可能明显延长,对启动时间要求苛刻的系统可能不适用。
  • 潜在内存浪费:预先分配所有对象内存可能造成一定程度的浪费,如果实际内存需求低于最坏情况,则会占用额外的内存空间。

总结:静态分配模式适用于最坏情况可预测、内存负载稳定、规模较小且对内存成本不敏感的系统。它能带来更快的运行速度、更可预测的执行和无碎片化等优势,但需要付出启动时间较长和潜在内存浪费的代价。

6.2.6 实施策略

这个模式非常容易实现。在许多情况下,甚至不需要单独的初始化方法,可以直接使用每个复合对象的构造函数来完成对象的创建和初始化。

6.2.7 相关模式

本章中介绍的其他模式也解决了类似的问题,但会带来略有不同的利弊。例如,池分配模式、固定大小缓冲区模式、垃圾回收器模式和垃圾压缩器模式等等。

6.2.8 示例模型

图6-2展示了一个使用完全构建系统实例的简单例子。图6-2a展示了对象图的实例结构,图6-2b展示了静态分配模式在启动时的工作方式。

总结来说,静态分配模式通过在系统启动时分配所有对象,避免了动态内存分配带来的时间不确定性和内存碎片化问题。这种模式适用于内存负载可预测、系统设计简单且内存成本不是主要考虑因素的情况。在实施时,需要在设计阶段对内存需求有准确的预测,以确保在最坏情况下有足够的内存。

图形中各个箭头的含义

  • 实线箭头:代表对象之间的组合关系

图形中各个对象的含义

  • 起搏器对象(Pacemaker Object):这是整个起搏器设备的总称。
    • 电池系统(Battery Subsystem):为起搏器提供动力。
      • 电池传感器(Battery Sensor):监测电池的电压,并在电池电量不足时向起搏器发出警报。
    • 通信子系统(Comm Subsystem):允许起搏器与外部设备(如程序器和监控系统)进行通信。它使用无线遥测系统来传输和接收数据。
      • 磁簧开关(Reed Switch):检测起搏器是否置于磁场中。这可用于激活起搏器的某些功能,例如遥测。
      • 消息队列(Message Queue):用于存储由通信子系统传输或接收的数据。
      • 收发器线圈(Transceiver Coil):用于无线传输和接收数据。
    • 起搏子系统(Pacing Subsystem):起搏器的核心
      • 心房(Atrial Chamber):心脏的上腔。
        • A 心脏传感器(A Heart Sensor):监测心房的电活动。
        • A 起搏电容器(A Pacing Canacitor):为起搏电路存储能量。
      • 心室(Ventricular Chamber):心脏的下腔。
        • V 心脏传感器(V Heart Sensor):监测心室的电活动。
        • V 起搏电容器(V Pacing Capacitor):为起搏电路存储能量。

起搏子系统(Pacing Subsystem):起搏器的核心,负责生成电脉冲来刺激心肌。它由起搏电路、起搏电极和起搏电容器组成。

  • 起搏电路(Pacing Circuit):生成电脉冲。
  • 起搏电极(Pacing Electrode):将脉冲传递给心肌。
  • 起搏电容器(Pacing Capacitor):为起搏电路存储能量。

http://www.jsqmd.com/news/849477/

相关文章:

  • 2026年评价高的零排放/重金属废水零排放/南京矿井废水零排放横向对比厂家推荐 - 品牌宣传支持者
  • NLP-Models-Tensorflow核心组件深度剖析:Attention机制与编码器设计
  • Speakeasy安全研究:仿真环境中的反调试与反仿真技术对抗
  • Prompt Engineering 2026 进阶实战:CoT/ReAct/DSPy,从入门到精通
  • Unity Timeline实战:除了过场动画,你的Signal Track和Control Track用对了吗?
  • 深入理解SPI四种模式:以STM32读写W25Q64为例,图解时序差异与配置要点
  • 为什么很多企业,最后真正被拖垮的,其实是“系统维护成本”?——真正昂贵的,从来不是“开发系统”,而是“长期维护复杂系统”
  • CANN/asc-devkit CastDequant函数
  • Amov二次开发
  • 构建高性能Windows RTMP流媒体服务器:nginx-rtmp-win32架构设计与部署实践
  • 告别龟速!实测PyTorch在Mac M1 GPU(MPS)上跑ResNet比CPU快了多少?
  • 选新疆管道厂家不踩坑!鑫贝弘螺旋钢管管件支吊架,防腐保温涂塑钢管喷砂除锈,外贸管件管道加工实力商家 - 栗子测评
  • Win11安全中心总弹警告?手把手教你揪出并删除那个‘捣乱’的内存完整性不兼容驱动
  • Ubuntu 20.04 + RTX 3090 保姆级教程:从零搞定BEVFusion环境(附CUDA 11.3/PyTorch 1.10配置清单)
  • 2026年比较好的南京矿井废水零排放/南京酸洗废水零排放/重金属废水零排放/含镍废水零排放长期合作厂家推荐 - 行业平台推荐
  • 如何3步实现IDM永久激活:终极注册表锁定技术详解
  • Egg.js重构Controller最佳实践:自定义核心组件与架构优化指南
  • 2026年京东云OpenClaw/Hermes Agent配置Token Plan快速上手指南
  • 最新孩子英语听说差难提升?这些实用软件亲测好用不踩坑
  • 别再死记硬背base64了!深入浅出聊聊CTF中那些‘魔改’编码的识别与对抗思路
  • LoRA/QLoRA 微调实战:单卡 GPU 训练自己的大模型,2026 完全指南
  • Embulk测试驱动开发:使用JUnit4构建可靠的插件测试
  • 广州增城区搬家公司搬红木家具收费标准 2026 最新避坑指南 - 从来都是英雄出少年
  • CANN/cannbot-skills 模型分析器代理
  • STM32F4 Discovery板ST-Link连接问题解决方案
  • SwiftPlate代码实现原理:深入理解字符串替换和模板处理机制
  • 扎根新疆!鑫贝弘管道设备制造,螺旋钢管管件支吊架外贸厂家,防腐保温涂塑钢管、喷砂除锈加工源头直供 - 栗子测评
  • CANN/hcomm通道描述符
  • Markdown Resume代码解析:Assetic资源管理与模板系统架构
  • 白天也能精准追踪!OpenMV强光下识别红色激光点的完整配置流程(附代码)