Skip to content

内存堆-按需分配内存块

李述铜

606字约2分钟

2025-08-30

除内存池外,RT-Thread还提供了内存堆,可以实现类似C标准库中的malloc()和free()提供的动态内存分配和释放的功能。

内存堆

内存堆是一块用于动态分配内存的区域,RT-Thread 在系统初始化时会将一段连续的RAM空间注册为堆区,用于,从而提供类似C标准库的malloc()和free()近似功能。

与C标准库函数不同之处

特别是在嵌入式系统中,内存分配的选择会影响性能、稳定性和实时性。因此,RT-Thread提供了自己的堆分配功能。与C标准库的内存分配接口之间的相比,其主要区别如下:

RT-Thread内存分配接口C 标准库内存分配接口
实现者RT-Thread 系统内核编译器或工具链的C标准库
是否可裁剪可按需启用或禁用难以裁剪
是否线程安全是,支持多线程默认不是线程安全
实时性更高(支持内存池)较低(不确定耗时)

三种不同的堆管理方法

由于不同嵌入式环境中,系统的资源数量不同,也就是RAM的大小、分布不同。因此,为了灵活地应对不同场景,RT-Thread提供了三种不同的堆管理方法。

alt text

在实际使用时,根据实际需要选择其中的一个即可。

示例代码:不连续的多个堆

#include "base.h"
#include <rtthread.h>
#include <stdlib.h>

static struct rt_mailbox mbox;

static rt_ubase_t mbox_buffer[8];

struct sensor_data {
    uint8_t temp;
    uint8_t hum;
};
static uint8_t mem_pool[8*(RT_ALIGN(sizeof(struct sensor_data), RT_ALIGN_SIZE) + sizeof(uint8_t *))];
static struct rt_mempool mpool;

static void sensor_read (struct sensor_data * data) {
    data->temp = 20 + rt_tick_get();
    data->hum = 50 + rt_tick_get();
}

void sender_entry (void * param) {    
    while (1) {
        struct sensor_data * data = (struct sensor_data *)rt_malloc(RT_WAITING_FOREVER);
        if (data != RT_NULL) {
            sensor_read(data);
            rt_mb_send_wait(&mbox, (rt_ubase_t)data, RT_WAITING_FOREVER);
        }
        
        rt_thread_mdelay(1000);
    }
}

void recv_entry (void * param) {
    while (1) {
        // recv
        struct sensor_data * data;
   
        rt_mb_recv(&mbox, (rt_ubase_t* )&data, RT_WAITING_FOREVER);
        
        //rt_kprintf("temp: %d, hum: %d\n", data->temp, data->hum);
        rt_free(data);
    }
}

static uint8_t heap1[10*1024];
struct  	rt_memheap mem_heap1;

static uint8_t heap2[10*1024];
struct  	rt_memheap mem_heap2;
int main(void) {
    hardware_init();
    
    rt_mb_init(&mbox, "mb", mbox_buffer, 8, RT_IPC_FLAG_FIFO);
    rt_memheap_init(&mem_heap1, "heap1", heap1, sizeof(heap1));
    rt_memheap_init(&mem_heap2, "heap12", heap2, sizeof(heap2));
    
    void * ptr1 = rt_malloc(5 * 1024);
    void * ptr2 = rt_malloc(5 * 1024);
    
    
    rt_thread_t t1 = rt_thread_create("t1", sender_entry, RT_NULL, 4096, 10, 10);
    rt_thread_startup(t1);
    rt_thread_t t2 = rt_thread_create("t2", recv_entry, RT_NULL, 4096, 10, 10);
    rt_thread_startup(t2);
    return 0;
}