这三种内存管理算法你知道吗?

智能硬件 创建于:2022-11-13

本文分享自中移OneOS公众号《内存管理》。

根据应用程序需求和系统资源的差异,操作系统提供了不同的内存分配管理算法,分别是小内存管理算法slab管理算法memheap管理算法

小内存管理算法主要针对系统RAM空间比较少的情况,一般用于小于2MB内存空间的系统,也是使用最广泛的内存管理算法。

slab内存管理算法则主要是在系统RAM空间比较丰富的情况,提供了一种近似内存池分配的快速算法。

memheap算法则用于系统存在多个内存堆的情况,它可以将多个内存连接在一起,形成一个大的内存堆,应用程序使用时感知不到多个内存堆的存在。

这几类内存堆管理算法在系统运行时只能选择其中之一或者完全不使用,他们提供给应用程序的API接口完全相同。

小内存管理算法

在小内存管理算法中,使用内存块的形式管理。

每个内存块都包含一个数据头,通过数据头把内存块用双向链表的方式连接起来,不论使用块或者空闲块都在同一个链表中管理。内存块的数据头数据结构定义如下:

struct os_heap_mem 
{ 
    os_uint16_t     magic;    /*魔数*/
    os_uint16_t     used;     /*使用标识*/
    os_size_t       prev;      /*指向前控制块的指针*/
    os_size_t       next;     /*指向后控制块的指针*/
};  

其中,next和prev用于双向链表的连接,magic是魔数,系统使用0x1ea0标识内存管理块的头部,同时通过该值可以检测内存非法改写的问题,如果该值变化即表示内存被非法写。used表示该内存块的分配状态。

内存管理的表现主要体现在内存的分配与释放上,分配内存时从空闲内存指针位置开始遍历,当找到一块足够大小内存块时,根据情况进行分割,前半部分返回给调用程序使用,分割后剩余的部分继续插入链表中。

下面举例说明申请内存的过程,空闲链表free指针指向64字节的内存块,当调用分配函数申请一个512字节的内存块时,64字节的内存不足,内存管理器开始遍历内存块,next指针指向的下一块内存头部的used为1已经被使用;查找到下一块未使用的内存并且大小为1024字节,满足请求大小,管理器使用分割功能,将申请的512字节加上12字节头部空间分成前半部分,used标记为已使用返回给应用;剩余的512字节空间,前面12字节用于数据头,剩余500字节用于数据体,used标记为0,并且插入双向链表中,如下图。

<内存分配示意图>

释放内存是相反的过程,内存管理器会查看前后相邻的内存块是否空闲,如果空闲则合并成一个大的空闲内存块,防止系统长时间运行后形成内存碎片。

 slab管理算法

slab是一个缓冲型的内存池算法。slab分配器是由多个区来管理内存,每一个区对应一类占用空间大小不同的对象,系统最多支持72种对象。

一个zone的大小在32K到128K字节之间,系统初始化时根据堆的大小自动调整。slab管理器一次最大能够分配16K的内存空间,如果超出了16K那么直接从页分配器中分配。每个zone上分配的内存块大小是固定的并且使用链表进行管理,而72种对象的zone链表则放在一个数组中统一管理,如下图。

<slab管理结构>

下面举例说明内存申请的过程,假设分配一个16字节的内存,slab内存分配器从zone array链表表头数组中找到对应的zone链表。如果链表为空,则向页分配器分配一个新的zone,然后从zone中返回第一个空闲内存块。如果链表非空,则链表中的第一个节点必然有空闲块存在,取相应的空闲块返回。如果分配完成后,此zone中所有空闲内存块都使用完毕,分配器会把这个zone节点从链表中删除。

内存释放时,分配器遍历zone_array,找到内存块所在的zone节点,然后把内存块连接到zone的空闲内存块链表中。如果此时zone的空闲链表中所有内存块都已经释放,当zone链表中全空闲zone达到一定数目后,系统就会把这个全空闲的zone释放到页面分配器中去。

memheap管理算法

如果系统含有多个地址不连续的内存堆,前面两种管理算法就不适用,操作系统提供了memheap管理算法解决这种场景。

如果指定使用该算法,在系统初始化时,就可以将多片不连续的内存加入memheap管理链表。当需要分配内存时,分配器首先从默认memheap中查找是否有剩余空间可用,如果有直接分配返回,如果已经不足分配则遍历链表,直到找到足够分配的memheap,从这里分配内存返回给应用。应用不需要关心从哪里分配的内存,简化了使用。

释放内存的过程类似,遍历链表查找到内存地址所在的memheap,释放地址空间。

内存管理接口设计如下:

(1)初始化内存堆

(2)分配内存块

(3)释放内存块

(4)重分配内存块

(5)分配多个内存块

(6)内存分配回调函数

(7)内存释放回调函数

原文地址:https://my.oschina.net/u/5443273/blog/5495567

免责声明:本文来源于互联网,版权归合法拥有者所有,如有侵权请公众号联系管理员

* 本站提供的一些文章、资料是供学习研究之用,如用于商业用途,请购买正版。

中移物联OneOS