外观
内存堆-按需分配内存块
除内存池外,RT-Thread还提供了内存堆,可以实现类似C标准库中的malloc()和free()提供的动态内存分配和释放的功能。
内存堆
内存堆是一块用于动态分配内存的区域,RT-Thread 在系统初始化时会将一段连续的RAM空间注册为堆区,用于,从而提供类似C标准库的malloc()和free()近似功能。
与C标准库函数不同之处
特别是在嵌入式系统中,内存分配的选择会影响性能、稳定性和实时性。因此,RT-Thread提供了自己的堆分配功能。与C标准库的内存分配接口之间的相比,其主要区别如下:
RT-Thread内存分配接口 | C 标准库内存分配接口 | |
---|---|---|
实现者 | RT-Thread 系统内核 | 编译器或工具链的C标准库 |
是否可裁剪 | 可按需启用或禁用 | 难以裁剪 |
是否线程安全 | 是,支持多线程 | 默认不是线程安全 |
实时性 | 更高(支持内存池) | 较低(不确定耗时) |
三种不同的堆管理方法
由于不同嵌入式环境中,系统的资源数量不同,也就是RAM的大小、分布不同。因此,为了灵活地应对不同场景,RT-Thread提供了三种不同的堆管理方法。
在实际使用时,根据实际需要选择其中的一个即可。
示例代码:不连续的多个堆
#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;
}