静态分配通过编译器在链接阶段确定内存位置,关键结构体:
typedef struct {
uint8_t ucDummy[configTOTAL_HEAP_SIZE]; // 静态内存池
} StaticAlloc_t;
// 实战示例:创建静态队列
StaticAlloc_t xHeap;
StaticQueue_t xQueueBuffer;
QueueHandle_t xQueue = xQueueCreateStatic(
10, // 队列长度
sizeof(Message_t), // 元素大小
(uint8_t*)&xHeap, // 存储区地址
&xQueueBuffer // 队列控制结构体
);
关键参数解析:
// 使用GCC段属性强制内存布局
__attribute__((section(".static_mem"))) static uint8_t ucHeap[1024];
__attribute__((section(".control_block"))) static StaticTask_t xTaskBuffer;
void vTaskCode(void *pv) {
// 任务代码...
}
xTaskCreateStatic(
vTaskCode, // 任务函数
"StaticTask", // 任务名
128, // 栈深度(单位字)
NULL, // 参数
tskIDLE_PRIORITY + 1,
ucHeap, // 任务栈
&xTaskBuffer // 任务控制块
);
内存布局验证:
arm-none-eabi-objdump -h
查看段分布算法类型 | 内部结构 | 碎片率 | 实时性 | 适用场景 |
---|---|---|---|---|
heap_1 | 单一大块 | 高 | O(1) | 初始化阶段 |
heap_2 | 最佳适应链表 | 中 | O(n) | 中等规模系统 |
heap_3 | malloc/free封装 | 高 | 不确定 | 兼容现有代码 |
heap_4 | 合并相邻空闲块 | 低 | O(n) | 长期运行系统 |
heap_5 | 多区域管理 | 最低 | O(n) | 复杂内存布局 |
// 根据系统特性选择算法
#if (SYSTEM_LIFE_CYCLE > 1000H) && (TOTAL_HEAP > 10KB)
#define USE_HEAP_4
#elif defined(FRAGMENTATION_SENSITIVE)
#define USE_HEAP_5
#else
#define USE_HEAP_2
#endif
// 安全封装函数
BaseType_t xSafeTaskCreate(
TaskFunction_t pxTaskCode,
const char *pcName,
uint16_t usStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask
) {
// 预分配内存检测
if(uxGetFreeHeapSize() < (usStackDepth * sizeof(StackType_t)) + sizeof(TCB_t)) {
return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
return xTaskCreate(
pxTaskCode,
pcName,
usStackDepth,
pvParameters,
uxPriority,
pxCreatedTask
);
}
// 使用示例
void vMainTask(void *pv) {
TaskHandle_t xHandle;
if(xSafeTaskCreate(vWorker, "Worker", 256, NULL, 2, &xHandle) == pdPASS) {
// 任务创建成功
} else {
// 内存不足处理
}
}
假设内存布局:
[已分配128][空闲64][已分配64][空闲128]
申请192字节时失败,尽管总空闲192字节!
// 内存分布扫描函数
void vCheckFragmentation() {
HeapStats_t xHeapStats;
vPortGetHeapStats(&xHeapStats);
printf("总空闲块: %d\n", xHeapStats.xNumberOfFreeBlocks);
printf("最大可用块: %d\n", xHeapStats.xSizeOfLargestFreeBlockInBytes);
if(xHeapStats.xNumberOfFreeBlocks > 10 &&
xHeapStats.xSizeOfLargestFreeBlockInBytes < 100) {
// 触发碎片整理
vCompactHeap();
}
}
// 自定义碎片整理(仅heap_5支持)
void vCompactHeap() {
vTaskSuspendAll();
// 合并相邻空闲块
prvMergeFreeBlocks();
xTaskResumeAll();
}
// 创建内存池
#define BLOCK_SIZE 64
#define NUM_BLOCKS 20
StaticAlloc_t xPool;
QueueHandle_t xMemPool = xQueueCreateSet(NUM_BLOCKS * BLOCK_SIZE);
void vInitPool() {
for(int i=0; i<NUM_BLOCKS; i++) {
xQueueSendToBack(xMemPool, &xPool[i*BLOCK_SIZE], 0);
}
}
void *pvAllocFixed() {
void *pvBlock;
if(xQueueReceive(xMemPool, &pvBlock, pdMS_TO_TICKS(10)) == pdPASS) {
return pvBlock;
}
return NULL;
}
typedef struct {
ListNode_t xList;
uint8_t ucData[64];
} CacheBlock_t;
#define CACHE_SIZE 10
CacheBlock_t xCache[CACHE_SIZE];
void vInitCache() {
for(int i=0; i<CACHE_SIZE; i++) {
vListInsertEnd(&xFreeList, &xCache[i].xList);
}
}
CacheBlock_t *pxAcquireCache() {
ListItem_t *pxItem = pxListGet(&xFreeList);
return (CacheBlock_t*)pxItem;
}
typedef struct {
void *pvAddress;
size_t xSize;
} SmartPointer_t;
void vSmartAlloc(SmartPointer_t *pxPtr, size_t xSize) {
pxPtr->pvAddress = pvPortMalloc(xSize);
pxPtr->xSize = xSize;
// 注册到全局链表
vListInsert(&xAllocList, (ListItem_t*)pxPtr);
}
void vSmartFree(SmartPointer_t *pxPtr) {
vPortFree(pxPtr->pvAddress);
// 从链表移除
uxListRemove((ListItem_t*)pxPtr);
// 填充释放区域(防野指针)
memset(pxPtr->pvAddress, 0xAA, pxPtr->xSize);
}
void vMemWatchdog(void *pv) {
while(1) {
HeapStats_t xStats;
vPortGetHeapStats(&xStats);
// 检测内存泄漏
static size_t xLastUsed = 0;
if(xStats.xAvailableHeapSpaceInBytes < xLastUsed) {
// 触发警报
}
xLastUsed = xStats.xAvailableHeapSpaceInBytes;
// 检测碎片率
float fFragFactor = (1.0 - (float)xStats.xSizeOfLargestFreeBlockInBytes /
xStats.xAvailableHeapSpaceInBytes) * 100;
if(fFragFactor > 30.0) {
// 触发碎片处理
}
vTaskDelay(pdMS_TO_TICKS(5000));
}
}
// 定义三个独立堆区
#define HEAP1_SIZE 2048
#define HEAP2_SIZE 4096
#define HEAP3_SIZE 1024
__attribute__((section(".heap1"))) static uint8_t ucHeap1[HEAP1_SIZE];
__attribute__((section(".heap2"))) static uint8_t ucHeap2[HEAP2_SIZE];
__attribute__((section(".heap3"))) static uint8_t ucHeap3[HEAP3_SIZE];
// 初始化heap_5
const HeapRegion_t xHeapRegions[] = {
{ ucHeap1, HEAP1_SIZE },
{ ucHeap2, HEAP2_SIZE },
{ ucHeap3, HEAP3_SIZE },
{ NULL, 0 } // 结束标记
};
vPortDefineHeapRegions(xHeapRegions);
// 定向分配函数
void *pvAllocFromHeap(size_t xSize, int iHeapIndex) {
if(iHeapIndex >= (sizeof(xHeapRegions)/sizeof(HeapRegion_t)) -1)
return NULL;
uint8_t *pucStart = xHeapRegions[iHeapIndex].pucStartAddress;
size_t xRemain = xHeapRegions[iHeapIndex].xSizeInBytes;
// 简单首次适应算法
while(xRemain >= xSize) {
if(*((uint32_t*)pucStart) == 0xFFFFFFFF) { // 检查是否空闲
*((uint32_t*)pucStart) = xSize; // 写入块头信息
return pucStart + sizeof(uint32_t);
}
pucStart += *((uint32_t*)pucStart);
xRemain -= *((uint32_t*)pucStart);
}
return NULL;
}
// 分配时填充特殊模式
void *pvDebugMalloc(size_t xSize) {
void *pv = pvPortMalloc(xSize + 8);
if(pv) {
// 前4字节填充0xAB
memset(pv, 0xAB, 4);
// 后4字节填充0xCD
memset((uint8_t*)pv + xSize + 4, 0xCD, 4);
return (void*)((uint8_t*)pv + 4);
}
return NULL;
}
// 释放时检查边界
void vDebugFree(void *pv) {
uint8_t *pReal = (uint8_t*)pv - 4;
assert(memcmp(pReal, "\xAB\xAB\xAB\xAB", 4) == 0);
assert(memcmp(pReal + *((size_t*)pReal) + 4, "\xCD\xCD\xCD\xCD", 4) == 0);
vPortFree(pReal);
}
void vPrintMemoryMap() {
uint8_t *puc = &_sheap; // 堆起始地址
while(puc < &_eheap) { // 堆结束地址
size_t xBlockSize = *((size_t*)puc);
printf("Addr: 0x%08X Size: %4d State: %s\n",
(unsigned)puc,
xBlockSize & ~0x1,
(xBlockSize & 0x1) ? "Used" : "Free");
puc += (xBlockSize & ~0x1);
}
}
通过上述方案,在某工业控制器项目中实现: