ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

【计算机基础】-49-Slab与Memory Pool内存空间来自哪里?初始化过程?申请和释放方法?代码示例?

【计算机基础】-49-Slab与Memory Pool内存空间来自哪里?初始化过程?申请和释放方法?代码示例?

在 RT-Thread 中,Slab AllocatorMemory Pool(rt_mp_t是两种独立的内存管理机制,它们的内存来源、初始化方式、申请/释放方法完全不同。下面从这四个方面详细对比,并附完整代码示例。


一、内存来源

机制内存来源
Slab Allocator来自系统堆(heap)<br>(即rt_system_heap_init()初始化的区域)
Memory Pool可来自:<br>1.系统堆(heap)(动态创建)<br>2.静态数组(静态创建,推荐用于 ISR)

关键区别

  • Slab只能从 heap 分配;
  • Memory Pool可选 heap 或静态内存。

二、初始化过程

1.Slab Allocator 初始化

  • 自动初始化:在rtthread_startup()中调用;
  • 前提:启用RT_USING_SLAB
  • 过程
    • 为每种内核对象(如 TCB、mutex)创建一个 slab cache;
    • cache 初始为空,首次分配时才从 heap 申请 slab。
// rtconfig.h #define RT_USING_SLAB // 系统启动时自动调用(用户无需干预) void rt_system_slab_init(void) { // 为 TCB 创建 cache rt_thread_slab = rt_slab_create("thread", sizeof(struct rt_thread), ...); // 为 semaphore 创建 cache... }

2.Memory Pool 初始化

  • 手动初始化:由用户调用 API 创建;
  • 两种方式
(1) 动态创建(从 heap 分配):rt_mp_create
rt_mp_t mp = rt_mp_create("mp", 64, 10); // 10 个 64 字节块
(2) 静态创建(使用静态数组):rt_mp_create_static
static uint8_t mp_buffer[64 * 10]; rt_mp_t mp = rt_mp_create_static("mp", 64, 10, mp_buffer);

推荐静态创建避免 heap 碎片,且 ISR 中更安全。


三、申请与释放方法

机制申请释放ISR 安全
Slab内核自动调用<br>(如rt_thread_create()内核自动调用<br>(如rt_thread_delete()⚠️ 间接支持
Memory Poolrt_mp_alloc(mp, timeout)rt_mp_free(block)✅ 直接支持

重要

  • 用户不能直接调用 Slab 的 alloc/free
  • Memory Pool 提供完整用户 API。

四、完整代码示例

场景:同时使用 Slab(线程) + Memory Pool(ISR 数据包)

#include <rtthread.h> /* ===== 1. Memory Pool 静态创建(推荐) ===== */ #define POOL_SIZE 10 #define BLOCK_SIZE 64 static uint8_t mp_buffer[BLOCK_SIZE * POOL_SIZE]; static rt_mp_t packet_pool = RT_NULL; /* ===== 2. 初始化函数 ===== */ int memory_init(void) { /* 创建静态 Memory Pool */ packet_pool = rt_mp_create_static("pkt_pool", BLOCK_SIZE, POOL_SIZE, mp_buffer); if (packet_pool == RT_NULL) { rt_kprintf("Failed to create memory pool\n"); return -1; } rt_kprintf("Memory pool created: %d blocks of %d bytes\n", POOL_SIZE, BLOCK_SIZE); return 0; } INIT_APP_EXPORT(memory_init); /* ===== 3. ISR 使用 Memory Pool ===== */ extern rt_mailbox_t data_mb; // 假设已创建邮箱 void uart_rx_isr(void) { // 从 Memory Pool 分配(非阻塞) void *buf = rt_mp_alloc(packet_pool, RT_WAITING_NO); if (buf) { // 模拟读取数据 *((int*)buf) = rt_tick_get(); // 存入时间戳 // 发送给线程处理 rt_mb_send(data_mb, (rt_ubase_t)buf); } // 若失败,丢包(无 heap 依赖,安全) } /* ===== 4. 线程处理并释放 ===== */ void data_process_thread(void *param) { rt_ubase_t msg; while (1) { if (rt_mb_recv(data_mb, &msg, RT_WAITING_FOREVER) == RT_EOK) { void *buf = (void *)msg; rt_kprintf("Received: tick=%d\n", *((int*)buf)); rt_mp_free(buf); // 归还到 Memory Pool } } } /* ===== 5. Slab 自动用于线程创建 ===== */ void create_worker_threads(void) { // 这些 TCB 由 Slab 从 heap 分配(零碎片) for (int i = 0; i < 3; i++) { char name[8]; rt_sprintf(name, "worker%d", i); rt_thread_t t = rt_thread_create(name, data_process_thread, RT_NULL, 512, 20, 10); rt_thread_startup(t); } } MSH_CMD_EXPORT(create_worker_threads, create workers);

五、内存布局示意

+---------------------------+ | System Heap (from linker) | ← rt_system_heap_init() | | | +-----------------------+ | | | Slab Cache (TCB) | | ← Slab 从 heap 切出 | | [TCB][TCB][TCB]... | | | +-----------------------+ | | | | (其他 heap 用户数据...) | +---------------------------+ +---------------------------+ | Static Memory (BSS) | | | | +-----------------------+ | | | mp_buffer[64*10] | | ← Memory Pool 静态数组 | +-----------------------+ | +---------------------------+

💡 如果 Memory Pool 动态创建,则其控制块和内存也来自 heap。


六、关键注意事项

项目SlabMemory Pool
是否需要用户管理❌ 否(内核自动)✅ 是
能否在 ISR 使用❌ 不能直接使用✅ 能(RT_WAITING_NO
内存碎片无(固定大小)无(固定大小)
适用对象内核对象(TCB等)用户数据(包、帧等)

✅ 总结

维度Slab AllocatorMemory Pool
内存来源系统堆(heap)heap 或静态数组
初始化系统自动用户手动(rt_mp_create
申请/释放内核自动(通过对象 API)用户显式(rt_mp_alloc/free
典型用途线程、信号量等内核对象ISR 数据包、固定帧缓冲区

🔑最佳实践

  • 内核对象 → 依赖 Slab(无需干预)
  • 用户实时数据 → 用静态 Memory Pool

两者共存无冲突,是构建高性能 RTOS 应用的黄金组合。

返回列表