Zephyr 提供了多种内存管理机制,适应从资源受限的嵌入式设备到复杂的应用需求。
| 方式 | 特点 | 适用场景 |
|---|---|---|
| 静态内存 | 编译时确定,无运行时开销 | 固定大小的缓冲区、栈 |
| 内存池 (Memory Pool) | 固定块大小,无碎片 | 频繁的固定大小分配 |
| 堆 (Heap) | 动态大小,可能有碎片 | 大小变化的分配 |
| 内存映射 | MMU/MPU 支持 | 内存保护、用户模式 |
/* 静态数组 */
static uint8_t tx_buffer[256];
static struct my_struct instance;
/* 线程栈 */
K_THREAD_STACK_DEFINE(my_stack, 1024);
/* 内核对象 */
struct k_mutex my_mutex;
struct k_sem my_sem;
/* 静态定义消息队列缓冲区 */
K_MSGQ_DEFINE(my_msgq, sizeof(struct event), 10, 4);
/* 静态定义管道 */
K_PIPE_DEFINE(my_pipe, 256);
/* 静态定义堆栈 */
K_STACK_DEFINE(my_stack, 20);
内存池分配固定大小的块,无碎片问题。
/* 定义内存池 - 8字节块,最多16个 */
K_MEM_POOL_DEFINE(my_pool, 8, 8, 16, 4);
/* 分配内存 */
struct k_mem_block block;
int ret = k_mem_pool_alloc(&my_pool, &block, 8, K_FOREVER);
if (ret == 0) {
/* 使用 block.data */
memcpy(block.data, data, 8);
/* 释放内存 */
k_mem_pool_free(&block);
}
/* 定义 slab - 每个块 64 字节,共 10 个块 */
K_MEM_SLAB_DEFINE(my_slab, 64, 10, 4);
void *ptr;
/* 分配 */
if (k_mem_slab_alloc(&my_slab, &ptr, K_NO_WAIT) == 0) {
/* 使用 ptr */
memset(ptr, 0, 64);
/* 释放 */
k_mem_slab_free(&my_slab, ptr);
}
/* 查询状态 */
int used = 10 - k_mem_slab_num_free_get(&my_slab);
printk("Used blocks: %d\n", used);
CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION=y # 跟踪最大使用量
/* 需要启用堆 */
CONFIG_HEAP_MEM_POOL_SIZE=4096
/* 分配 */
void *ptr = k_malloc(256);
if (ptr) {
/* 使用 */
memset(ptr, 0, 256);
/* 重新分配 */
ptr = k_realloc(ptr, 512);
/* 释放 */
k_free(ptr);
}
/* 按 32 字节对齐分配 */
void *aligned_ptr = k_aligned_alloc(32, 256);
if (aligned_ptr) {
/* aligned_ptr 是 32 字节对齐的 */
k_free(aligned_ptr);
}
/* 查询堆状态 */
struct sys_heap_stats stats;
k_heap_stats(&stats);
printk("Free: %zu bytes\n", stats.free_bytes);
printk("Allocated: %zu bytes\n", stats.allocated_bytes);
printk("Max alloc: %zu bytes\n", stats.max_alloc_bytes);
#include <zephyr/kernel.h>
/* 使用 RAII 管理内存 */
std::unique_ptr<uint8_t[]> buffer(new uint8_t[256]);
/* 或者使用自定义删除器 */
auto deleter = [](void *p) { k_free(p); };
std::unique_ptr<uint8_t, decltype(deleter)>
ptr((uint8_t *)k_malloc(256), deleter);
#ifdef CONFIG_USERSPACE
/* 定义内存域 */
struct k_mem_partition partitions[] = {
/* 代码段 */
{.start = (uint32_t)&_image_text_start,
.size = (uint32_t)&_image_text_size,
.attr = K_MEM_PARTITION_P_RX_U_RX},
/* 数据段 */
{.start = (uint32_t)&_image_rodata_start,
.size = (uint32_t)&_image_rodata_size,
.attr = K_MEM_PARTITION_P_RO_U_RO},
};
struct k_mem_domain domain;
k_mem_domain_init(&domain, 2, partitions);
/* 将线程添加到域 */
k_mem_domain_add_thread(&domain, k_current_get());
#endif
/* 启用 MPU */
CONFIG_ARM_MPU=y
/* 定义保护区域 */
struct arm_mpu_region regions[] = {
/* 闪存 - 只读 */
{.base = 0x08000000,
.attr = REGION_RAM_ATTR},
/* RAM - 读写 */
{.base = 0x20000000,
.attr = REGION_RAM_ATTR},
};
/* ✅ 推荐:静态分配 */
static uint8_t buffer[MAX_SIZE];
/* ❌ 避免:频繁动态分配 */
for (int i = 0; i < 1000; i++) {
void *ptr = k_malloc(size); /* 碎片! */
/* ... */
k_free(ptr);
}
/* ✅ 推荐:使用内存池 */
K_MEM_SLAB_DEFINE(packet_slab, 64, 10, 4);
for (int i = 0; i < 1000; i++) {
void *ptr;
if (k_mem_slab_alloc(&packet_slab, &ptr, K_NO_WAIT) == 0) {
/* ... */
k_mem_slab_free(&packet_slab, ptr);
}
}
/* ✅ 对齐到缓存行 */
#define CACHE_LINE_SIZE 32
__aligned(CACHE_LINE_SIZE) static uint8_t dma_buffer[1024];
/* 或运行时对齐 */
void *aligned_ptr = k_aligned_alloc(CACHE_LINE_SIZE, size);
/* 启用栈保护 */
CONFIG_STACK_SENTINEL=y
CONFIG_STACK_CANARIES=y
/* 线程栈大小设计 */
#define THREAD_STACK_SIZE 2048 /* 根据实际需求 */
K_THREAD_STACK_DEFINE(my_stack, THREAD_STACK_SIZE);
/* 运行时检查栈使用量 */
size_t unused = k_thread_stack_space_get(my_thread_id);
printk("Unused stack: %zu bytes\n", unused);
/* 启用内存跟踪 */
CONFIG_TRACING=y
CONFIG_TRACING_BACKEND_RAM=y
/* 或使用自定义钩子 */
void *my_malloc(size_t size, const char *file, int line)
{
void *ptr = k_malloc(size);
LOG_INF("ALLOC: %p size=%zu at %s:%d", ptr, size, file, line);
return ptr;
}
#define k_malloc(s) my_malloc(s, __FILE__, __LINE__)
# 内核内存
CONFIG_MAIN_STACK_SIZE=2048 # 主线程栈
CONFIG_IDLE_STACK_SIZE=256 # 空闲线程栈
CONFIG_ISR_STACK_SIZE=2048 # 中断栈
# 堆内存
CONFIG_HEAP_MEM_POOL_SIZE=8192 # 堆总大小
# 内存池
CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION=y
# 内存保护
CONFIG_ARCH_HAS_USERSPACE=y
CONFIG_USERSPACE=y
CONFIG_MPU_STACK_GUARD=y
CONFIG_STACK_SENTINEL=y
extern char _image_rom_start[];
extern char _image_rom_end[];
extern char _image_ram_start[];
extern char _image_ram_end[];
extern char __bss_start[];
extern char __bss_end[];
void print_memory_layout(void)
{
printk("ROM: %p - %p (size: %d)\n",
_image_rom_start, _image_rom_end,
_image_rom_end - _image_rom_start);
printk("RAM: %p - %p (size: %d)\n",
_image_ram_start, _image_ram_end,
_image_ram_end - _image_ram_start);
printk("BSS: %p - %p (size: %d)\n",
__bss_start, __bss_end,
__bss_end - __bss_start);
}
#include <zephyr/kernel.h>
void print_memory_stats(void)
{
/* 栈统计 */
printk("Stack usage:\n");
k_thread_foreach(thread_stats_cb, NULL);
/* 堆统计 */
struct sys_heap_stats stats;
k_heap_stats(&stats);
printk("Heap: free=%zu, alloc=%zu\n",
stats.free_bytes, stats.allocated_bytes);
}
*学习笔记创建时间: 2026-03-19*