全部文档
OneOS简介 硬件支持 编译构造工具 API参考文档 高级语言 用户编程手册 应用笔记 FAQ

内存堆管理


简介

内存堆管理可以在当前资源满足的前提下,根据用户的需求分配任意大小的内存,当用户不再使用时,可以释放回堆中。本操作系统提供了几种内存管理算法,包括小内存管理算法、slab管理算法和memheap管理算法。

小内存算法在最开始时是一块完整的大内存。分配内存实际上就是寻找第一个大于等于实际需求(申请大小加数据头大小)的空闲块并分割出来,剩余部分还回给堆管理系统。释放内存时,也会把释放的内存还回给堆管理系统,相邻有空闲块时会合并在一起。随着内存的不断分配和释放,原始的大内存被分成了多个大小不一的使用内存块和空闲内存块。每个内存块包含两部分,一是用于内存管理的数据头(包括链表指针、使用标志等),另外一部分为实际返回的可供用户使用的空间。

slab管理算法是由slab分配器修改而来,在运行过程中,会把内存分成不同尺寸的zone,每个zone中划分成多个相同大小的内存块。相同大小的内存块链接在一个zone的链表中,而不同的zone则通过数组管理。最多包含72种zone,一次最大可以分配16K的空间,超出时直接从页分配器中分配。

memheap管理算法可用于系统中含有多个地址不连续的内存堆,即用户可以将多个(地址可不连续)memheap合在一起使用。其具体分配算法和小内存算法比较相似。

内存堆管理有一套统一的接口,如os_malloc、 os_free等;memheap管理另外还有一套接口,如os_memheap_alloc、os_memheap_free。

内存堆管理可以有以下配置组合:

(1)OS_USING_HEAP + OS_USING_MEM_SMALL,采用小内存管理算法,操作接口为os_system_heap_init、os_malloc、 os_free等;

(2)OS_USING_HEAP + OS_USING_MEM_SLAB,采用slab管理算法,操作接口为os_system_heap_init、os_malloc、 os_free等;

(3)OS_USING_HEAP + OS_USING_MEM_HEAP + OS_USING_MEM_HEAP_AS_HEAP,采用memheap算法,操作接口为os_system_heap_init、os_malloc、 os_free等(此种配置下,若有多个不连续的堆,第一个堆使用os_system_heap_init初始化后,其它堆使用os_memheap_init初始化,之后使用os_malloc时系统会先到第一个堆上去分配,若分配不到则会去其它堆上分配);

(4)OS_USING_HEAP + OS_USING_MEM_SMALL + OS_USING_MEM_HEAP,采用小内存管理算法,操作接口为os_system_heap_init、os_malloc、 os_free等;但是同时支持memheap算法,使用os_memheap_init初始化的内存区域,操作接口为os_memheap_alloc、os_memheap_free等;

(5)OS_USING_HEAP + OS_USING_MEM_SLAB + OS_USING_MEM_HEAP,采用slab管理算法,操作接口为os_system_heap_init、os_malloc、 os_free等;但是同时支持memheap算法,使用os_memheap_init初始化的内存区域,操作接口为os_memheap_alloc、os_memheap_free等。


API列表

接口 说明
os_system_heap_init 堆初始化接口,系统初始化时调用
os_malloc 从内存堆上分配指定大小的内存
os_realloc 重新分配内存,并保留原数据
os_calloc 分配连续的多个内存块
os_free 释放内存
os_malloc_align 分配由align指定的字节对齐的内存
os_free_align 释放由os_malloc_align()分配的内存
os_memheap_init 用memheap管理算法初始化一块内存
os_memheap_deinit 反初始化memheap管理算法的内存
os_memheap_alloc 在os_memheap_init()初始化的内存块上分配一块内存
os_memheap_realloc 调整通过os_memheap_alloc()分配的内存
os_memheap_free 释放通过os_memheap_alloc()分配的内存

os_system_heap_init

该函数为内存堆管理的初始化接口,使用内存堆管理时,必须在系统初始化时调用此接口,函数原型如下:

void os_system_heap_init(void *begin_addr, void *end_addr);
参数 说明
begin_addr 内存堆的起始地址
end_addr 内存堆的结束地址
返回 说明

os_malloc

该函数从内存堆上分配指定大小的内存,函数原型如下:

void *os_malloc(os_size_t nbytes);
参数 说明
nbytes 分配内存的大小
返回 说明
非OS_NULL 分配成功,返回分配的内存地址
OS_NULL 分配失败

os_realloc

该函数重新分配内存,并保留原有数据(若缩小内存,会截断数据),函数原型如下:

void *os_realloc(void *ptr, os_size_t nbytes);
参数 说明
ptr 原有已分配内存的地址
nbytes 新内存大小
返回 说明
非OS_NULL 重新分配成功,返回调整之后的内存地址,此地址可能与原有地址不同
OS_NULL 重新分配失败

os_calloc

该函数分配连续的多个内存块,并初始化为0,函数原型如下:

void *os_calloc(os_size_t count, os_size_t size);
参数 说明
count 元素的个数
size 每个元素的字节数
返回 说明
非OS_NULL 分配成功,且内存区域初始化为0
OS_NULL 分配失败

os_free

该函数释放由os_malloc/os_realloc/os_calloc等分配的内存,函数原型如下:

void  os_free(void *ptr);
参数 说明
ptr 待释放内存的地址
返回 说明

os_malloc_align

该函数分配由allign指定的字节对齐的内存,allign的大小本身按照4对齐,函数原型如下:

void *os_malloc_align(os_size_t size, os_size_t align);
参数 说明
size 分配内存的大小
align 对齐的大小,allign本身按照4对齐;例如:若align是3,则申请内存的首地址按照4对齐;若allign是5,则申请内存的首地址按照8字节对齐
返回 说明
非OS_NULL 分配成功,返回对齐的首地址
OS_NULL 分配失败

os_free_align

该函数释放由os_malloc_align()分配的内存,函数原型如下:

void os_free_align(void *ptr);
参数 说明
ptr 待释放内存的地址
返回 说明

os_memheap_init

该函数采用memheap管理算法初始化一块内存,函数原型如下:

os_err_t os_memheap_init(struct os_memheap *memheap,
                         const char        *name,
                         void              *start_addr,
                         os_size_t         size);
参数 说明
memheap memheap句柄
name 名字
start_addr 起始地址
size memheap大小
返回 说明
OS_EOK 初始化成功

os_memheap_deinit

该函数反初始化内存,与os_memheap_init()匹配使用,函数原型如下:

os_err_t os_memheap_deinit(struct os_memheap *heap);
参数 说明
heap memheap句柄
返回 说明
OS_EOK 反初始化成功

os_memheap_alloc

该函数在指定memheap上分配内存,函数原型如下:

void *os_memheap_alloc(struct os_memheap *heap, os_size_t size);
参数 说明
heap memheap句柄
size 分配内存的大小
返回 说明
非OS_NULL 分配成功,返回分配的内存地址
OS_NULL 分配失败

os_memheap_realloc

该函数调整原有分配内存的大小,函数原型如下:

void *os_memheap_realloc(struct os_memheap *heap, void *ptr, os_size_t newsize);
参数 说明
heap memheap句柄
ptr 待调整的内存地址
newsize 待重新分配的新大小
返回 说明
非OS_NULL 调整成功,返回分配的内存地址
OS_NULL 调整失败

os_memheap_free

该函数释放由os_memheap_alloc()或os_memheap_realloc()申请的内存,函数原型如下:

void os_memheap_free(void *ptr);
参数 说明
ptr 待释放内存的地址
返回 说明

使用示例

内存堆管理使用示例

本例配置为OS_USING_HEAP + OS_USING_MEM_SMALL,即采用小内存管理算法。展示了使用os_malloc和os_free申请和释放内存,使用os_realloc重新分配内存,注意os_realloc重新分配内存的地址可能与原始地址不同

#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <shell.h>
#include <os_memory.h>

#define TEST_TAG        "TEST"

#define TEST_MALLOC_TIMES   20

void memory_sample(void)
{
    os_uint32_t i = 0;    
    os_uint32_t size = 0;    
    void *ptr = OS_NULL;    
    void *ptr_new = OS_NULL;
    void *ptr_old = OS_NULL;

    for (i = 0; i < TEST_MALLOC_TIMES; i++)
    {
        size = (1 << i);
        ptr = os_malloc(size);

        if (ptr)
        {
            LOG_W(TEST_TAG, "malloc memory:%p size:%d", ptr, size);
            os_free(ptr);
            LOG_W(TEST_TAG, "free memory  :%p size:%d", ptr, size);
            ptr = OS_NULL;
        }
        else
        {
            LOG_W(TEST_TAG, "try to get %d byte memory failed!", size);
            break;
        }
    }

    ptr_new = os_malloc(100);
    if (ptr_new)
    {
        LOG_W(TEST_TAG, "malloc memory:%p size:%d", ptr_new, 100);
    }
    else
    {
        LOG_W(TEST_TAG, "try to get %d byte memory failed!", 100);
    } 
    for (i = 0; i < TEST_MALLOC_TIMES; i++)
    {        
        size = (1 << i);
        ptr_old = ptr_new;
        ptr_new = os_realloc(ptr_old, size);
        if (ptr_new)
        {
            LOG_W(TEST_TAG, "realloc memory:%p size:%d", ptr_new, size);
        }
        else
        {
            LOG_W(TEST_TAG, "try to realloc %d byte memory failed!", size);
            os_free(ptr_old);
            break;
        }
    }
    if (ptr_new)
    {
        os_free(ptr_new);
    }
}

SH_CMD_EXPORT(test_memory, memory_sample, "test memory");

运行结果如下:

sh />test_memory
W/TEST: malloc memory:20007800 size:1
W/TEST: free memory  :20007800 size:1
W/TEST: malloc memory:20007800 size:2
W/TEST: free memory  :20007800 size:2
W/TEST: malloc memory:20007800 size:4
W/TEST: free memory  :20007800 size:4
W/TEST: malloc memory:20007800 size:8
W/TEST: free memory  :20007800 size:8
W/TEST: malloc memory:20007800 size:16
W/TEST: free memory  :20007800 size:16
W/TEST: malloc memory:20007800 size:32
W/TEST: free memory  :20007800 size:32
W/TEST: malloc memory:20007800 size:64
W/TEST: free memory  :20007800 size:64
W/TEST: malloc memory:20007800 size:128
W/TEST: free memory  :20007800 size:128
W/TEST: malloc memory:20007800 size:256
W/TEST: free memory  :20007800 size:256
W/TEST: malloc memory:20007800 size:512
W/TEST: free memory  :20007800 size:512
W/TEST: malloc memory:20007800 size:1024
W/TEST: free memory  :20007800 size:1024
W/TEST: malloc memory:20007800 size:2048
W/TEST: free memory  :20007800 size:2048
W/TEST: malloc memory:20007800 size:4096
W/TEST: free memory  :20007800 size:4096
W/TEST: malloc memory:20007800 size:8192
W/TEST: free memory  :20007800 size:8192
W/TEST: malloc memory:20007800 size:16384
W/TEST: free memory  :20007800 size:16384
W/TEST: malloc memory:20007800 size:32768
W/TEST: free memory  :20007800 size:32768
W/TEST: malloc memory:20007800 size:65536
W/TEST: free memory  :20007800 size:65536
E/MSMALL: no memory
W/TEST: try to get 131072 byte memory failed!
W/TEST: malloc memory:20007800 size:100
W/TEST: realloc memory:20007800 size:1
W/TEST: realloc memory:20007800 size:2
W/TEST: realloc memory:20007800 size:4
W/TEST: realloc memory:20007814 size:8
W/TEST: realloc memory:20007830 size:16
W/TEST: realloc memory:20007800 size:32
W/TEST: realloc memory:20007830 size:64
W/TEST: realloc memory:20007880 size:128
W/TEST: realloc memory:20007910 size:256
W/TEST: realloc memory:20007a20 size:512
W/TEST: realloc memory:20007c30 size:1024
W/TEST: realloc memory:20008040 size:2048
W/TEST: realloc memory:20008850 size:4096
W/TEST: realloc memory:20009860 size:8192
W/TEST: realloc memory:2000b870 size:16384
W/TEST: realloc memory:2000f880 size:32768
W/TEST: try to realloc 65536 byte memory failed!

memheap管理算法接口使用示例

本例配置为OS_USING_HEAP + OS_USING_MEM_SMALL + OS_USING_MEM_HEAP,即采用小内存管理算法。开始时使用标准的堆管理接口分配出一块内存,然后使用memheap管理算法的接口来初始化这块内存,之后就可以使用memheap的接口来分配和释放这块内存

#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <shell.h>
#include <os_memory.h>

#define TEST_TAG        "TEST"

#define TEST_MALLOC_TIMES   20

static struct os_memheap memheap_test;

void memory_heap_sample(void)
{
    void *ptr = OS_NULL;
    void *ptr_new = OS_NULL;
    void *ptr_old = OS_NULL;
    void *start_addr = OS_NULL;
    os_uint32_t size = 2000;
    os_err_t err;
    os_uint32_t i = 0;

    start_addr = os_malloc(size);
    if (!start_addr)
    {
        return;
    }

    err = os_memheap_init(&memheap_test, "memheap1", start_addr, size);
    if (err == OS_EOK)
    {
        LOG_W(TEST_TAG, "init memheap_test, start_addr:%p size:%d", start_addr, size);
    }
    else
    {
        LOG_W(TEST_TAG, "failed to init memheap_test");
        return;
    }

    for (i = 0; i < TEST_MALLOC_TIMES; i++)
    {
        size = (1 << i);
        ptr = os_memheap_alloc(&memheap_test, size);

        if (ptr)
        {
            LOG_W(TEST_TAG, "memheap_alloc:%p size:%d", ptr, size);
            os_memheap_free(ptr);
            LOG_W(TEST_TAG, "memheap_free :%p size:%d", ptr, size);
            ptr = OS_NULL;
        }
        else
        {
            LOG_W(TEST_TAG, "try to memheap_alloc %d byte failed", size);
            break;
        }
    }

    size = 100;
    ptr_new = os_memheap_alloc(&memheap_test, size);
    if (ptr_new)
    {
        LOG_W(TEST_TAG, "memheap_realloc memory:%p size:%d", ptr_new, size);
    }
    else
    {
        LOG_W(TEST_TAG, "try to memheap_alloc %d byte memory failed!", size);
        return;
    } 
    for (i = 0; i < TEST_MALLOC_TIMES; i++)
    {        
        size = (1 << i);
        ptr_old = ptr_new;
        ptr_new = os_memheap_realloc(&memheap_test, ptr_old, size);
        if (ptr_new)
        {
            LOG_W(TEST_TAG, "memheap_realloc memory:%p size:%d", ptr_new, size);
        }
        else
        {
            LOG_W(TEST_TAG, "try to memheap_realloc %d byte memory failed!", size);
            os_memheap_free(ptr_old);
            break;
        }
    }
    if(ptr_new)
    {
        os_memheap_free(ptr_new);
    }

    os_memheap_deinit(&memheap_test);
    os_free(start_addr);
}

SH_CMD_EXPORT(test_memory_heap, memory_heap_sample, "test memory heap");

运行结果如下:

sh />test_memory_heap
W/TEST: init memheap_test, start_addr:20007888 size:2000
W/TEST: memheap_alloc:200078a0 size:1
W/TEST: memheap_free :200078a0 size:1
W/TEST: memheap_alloc:200078a0 size:2
W/TEST: memheap_free :200078a0 size:2
W/TEST: memheap_alloc:200078a0 size:4
W/TEST: memheap_free :200078a0 size:4
W/TEST: memheap_alloc:200078a0 size:8
W/TEST: memheap_free :200078a0 size:8
W/TEST: memheap_alloc:200078a0 size:16
W/TEST: memheap_free :200078a0 size:16
W/TEST: memheap_alloc:200078a0 size:32
W/TEST: memheap_free :200078a0 size:32
W/TEST: memheap_alloc:200078a0 size:64
W/TEST: memheap_free :200078a0 size:64
W/TEST: memheap_alloc:200078a0 size:128
W/TEST: memheap_free :200078a0 size:128
W/TEST: memheap_alloc:200078a0 size:256
W/TEST: memheap_free :200078a0 size:256
W/TEST: memheap_alloc:200078a0 size:512
W/TEST: memheap_free :200078a0 size:512
W/TEST: memheap_alloc:200078a0 size:1024
W/TEST: memheap_free :200078a0 size:1024
W/TEST: try to memheap_alloc 2048 byte failed
W/TEST: memheap_realloc memory:200078a0 size:100
W/TEST: memheap_realloc memory:200078a0 size:1
W/TEST: memheap_realloc memory:200078a0 size:2
W/TEST: memheap_realloc memory:200078a0 size:4
W/TEST: memheap_realloc memory:200078a0 size:8
W/TEST: memheap_realloc memory:200078a0 size:16
W/TEST: memheap_realloc memory:200078a0 size:32
W/TEST: memheap_realloc memory:200078a0 size:64
W/TEST: memheap_realloc memory:200078a0 size:128
W/TEST: memheap_realloc memory:200078a0 size:256
W/TEST: memheap_realloc memory:200078a0 size:512
W/TEST: memheap_realloc memory:200078a0 size:1024
W/TEST: try to memheap_realloc 2048 byte memory failed!

results matching ""

    No results matching ""

    返回顶部