YueOS 开发日志 (1) - 内存管理
内存管理
内存管理的目标
建立合理的机制,将内存快速、高效(使用率)及安全的分配给需要的申请者。
内存申请行为的分类
对于内存申请行为有如下几种可能:
-
编译时确定
如果程序在设计时就能确定某种数据结构需要实例化的数量,应该优先使用全局变量。这样可以利用编译器来进行内存空间检查。如一辆脉轮小车底盘的电机速度环 PID 。
-
运行时确定
某种数据结构在编译时无法确定所有信息(如通信缓冲区大小或打开文件的数量)。这种情况下可以考虑使用堆内存。-
长时间持有
某些应用中,一旦申请内存,就几乎不会释放或是在可预见的时间段内都不会将其释放,这种情况称为长时间持有。
应按具体情况选择全局变量或是堆内存申请。 -
短时间持有
对于某些事件,可以明确估计出该事件的处理器的响应时间,从而估算出某内存空间的使用时间,这种情况被称为短时间持有的内存申请。- 若该事件频率较低且所需内存空间较小,则可考虑使用池内存
- 若频率较高或所需内存空间较大,则可考虑使用堆内存或全局变量。
-
内存管理的数据结构
内存堆
内存堆是一块连续的大容量内存空间。当用户申请内存时,将从内存堆上划分出一个完整的块分配给用户使用。这些被划分出的块是连续稠密的。
堆的用途
堆被设计出来尽可能高密度的分配空间。当多次申请/释放后,极易产生内存碎块。另外,在分配时会伴随着较复杂的分配查找算法,因此不适用于小内存、高申请密度的内存申请。
堆的结构
-
堆的元数据
-
堆
内存池
内存池是一块包含多个预分配块的内存栈。当用户申请时,弹出一块内存给用户使用;释放时重新压栈。
池的用途
堆被设计出来用以快速分配内存块,且避免了内存的碎片化。
池的结构
在池内未使用的内存块在逻辑上以栈的方式呈现(但由双向链表实现),但在使用时会将全部内存空间分配给用户。这样做避免了因链表结构占用而产生的浪费。
注意:因为一整块内存(包括链表信息)都将分配给用户,所以用户释放时需要重新作为链表结点初始化后再压栈。
GC
当内存被释放时,内存块不会直接被回收,而是标记为垃圾块,等待空闲时间时再由内核进程回收。
内存在释放时会进行完整性检查。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Reglucis 的博客!
