VxWorks核心内核模块:内存管理模块解析(第二部分)
2026/5/11 12:42:09 网站建设 项目流程

2.1 物理内存管理架构深度解析

2.1.1 物理内存管理的设计挑战

在实时嵌入式系统中,物理内存管理面临独特的挑战:

  1. 资源极度受限:嵌入式设备通常配备有限的内存(从几KB到几GB不等),必须高效利用

  2. 确定性要求:内存分配时间必须可预测,最坏情况执行时间(WCET)必须受限

  3. 硬件多样性:需支持多种内存类型(SRAM、DRAM、NOR/NAND Flash、DDR等)和架构

  4. 实时性约束:内存管理操作不能引入不可预测的延迟

  5. 安全隔离:关键系统组件需要内存保护,防止故障扩散

VxWorks的物理内存管理架构针对这些挑战进行了专门设计,在灵活性与确定性之间取得了精妙平衡。

2.2 物理内存初始化与探测机制

2.2.1 系统启动阶段的内存探测

VxWorks在启动过程中通过多阶段方式建立物理内存视图:

/* 内存探测与初始化流程 */ void sysPhysMemInit(void) { /* 阶段1:BSP提供的原始内存信息 */ MEM_DESC *bspMemDesc = bspGetMemoryDescriptors(); /* 阶段2:处理器特定内存初始化 */ cpuMemInit(); /* 阶段3:内存控制器初始化 */ memCtrlInit(); /* 阶段4:建立全局内存描述符表 */ buildGlobalMemMap(bspMemDesc); /* 阶段5:保留系统关键区域 */ reserveCriticalRegions(); /* 阶段6:初始化内存管理数据结构 */ initMemoryManager(); }

内存描述符数据结构

typedef struct mem_desc { PHYS_ADDR start; /* 起始物理地址 */ PHYS_ADDR end; /* 结束物理地址(start + size - 1) */ UINT32 size; /* 区域大小(字节) */ UINT16 type; /* 内存类型 */ UINT16 flags; /* 属性标志 */ char name[16]; /* 区域名称 */ struct mem_desc *next; /* 下一个描述符 */ } MEM_DESC; /* 内存类型定义 */ #define MEM_TYPE_RAM 0x0001 /* 可读写的RAM */ #define MEM_TYPE_ROM 0x0002 /* 只读内存 */ #define MEM_TYPE_FLASH 0x0004 /* Flash内存 */ #define MEM_TYPE_DEVICE 0x0008 /* 设备内存(内存映射I/O) */ #define MEM_TYPE_RESERVED 0x0010 /* 系统保留内存 */ #define MEM_TYPE_DMA 0x0020 /* DMA专用内存 */ #define MEM_TYPE_NON_CACHEABLE 0x0040 /* 不可缓存内存 */ /* 内存属性标志 */ #define MEM_FLAG_READABLE 0x0001 #define MEM_FLAG_WRITABLE 0x0002 #define MEM_FLAG_EXECUTABLE 0x0004 #define MEM_FLAG_CACHEABLE 0x0008 #define MEM_FLAG_BUFFERABLE 0x0010 #define MEM_FLAG_SHAREABLE 0x0020 #define MEM_FLAG_SECURE 0x0040 #define MEM_FLAG_UNCERTAIN 0x0080 /* 内存存在性不确定 */

2.2.2 内存区域自动检测算法

对于支持内存自动检测的平台,VxWorks实现了一套安全的内存探测算法:

/* 内存探测算法实现 */ STATUS memProbeRegion(PHYS_ADDR start, PHYS_ADDR end) { volatile UINT32 *testAddr; UINT32 pattern1 = 0xA5A5A5A5; UINT32 pattern2 = 0x5A5A5A5A; UINT32 originalValue; UINT32 readValue; /* 边界检查 */ if (end <= start) { return ERROR; } /* 按页对齐探测 */ for (PHYS_ADDR addr = start; addr < end; addr += PAGE_SIZE) { testAddr = (volatile UINT32 *)physToVirt(addr); /* 保存原始值 */ originalValue = *testAddr; /* 测试写入和读取 */ *testAddr = pattern1; asm volatile("dsb sy"); /* 内存屏障确保写入完成 */ asm volatile("isb sy"); /* 指令屏障 */ readValue = *testAddr; if (readValue != pattern1) { /* 写入失败,可能不是有效的RAM */ return ERROR; } /* 测试模式翻转 */ *testAddr = pattern2; asm volatile("dsb sy"); asm volatile("isb sy"); readValue = *testAddr; if (readValue != pattern2) { /* 模式翻转失败 */ *testAddr = originalValue; /* 尝试恢复原始值 */ return ERROR; } /* 恢复原始值 */ *testAddr = originalValue; } return OK; }

2.2.3 内存映射表构建

系统启动后构建全局内存映射表,为后续内存管理提供基础:

/* 全局内存映射表结构 */ typedef struct mem_map_table { MEM_DESC *descriptors; /* 内存描述符链表 */ UINT32 numRegions; /* 区域数量 */ UINT64 totalMemory; /* 总内存大小 */ UINT64 usableMemory; /* 可用内存大小 */ SEM_ID lock; /* 表访问锁 */ BOOL initialized; /* 初始化标志 */ } MEM_MAP_TABLE; /* 构建内存映射表 */ STATUS buildMemoryMap(MEM_MAP_TABLE *pTable, MEM_DESC *bspDescs) { MEM_DESC *current, *newDesc, *prev = NULL; UINT32 regionCount = 0; UINT64 totalMem = 0, usableMem = 0; if (pTable == NULL || bspDescs == NULL) { return ERROR; } /* 初始化表锁 */ pTable->lock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE); if (pTable->lock == NULL) { return ERROR; } semTake(pTable->lock, WAIT_FOREVER); /* 复制并规范化BSP提供的内存描述符 */ current = bspDescs; while (current != NULL) { /* 创建新的描述符副本 */ newDesc = (MEM_DESC *)malloc(sizeof(MEM_DESC)); if (newDesc == NULL) { semGive(pTable->lock); return ERROR; } memcpy(newDesc, current, sizeof(MEM_DESC)); /* 确保地址对齐 */ newDesc->start = ALIGN_DOWN(newDesc->start, PAGE_SIZE); newDesc->end = ALIGN_UP(newDesc->end, PAGE_SIZE) - 1; newDesc->size = newDesc->end - newDesc->start + 1; /* 添加到链表 */ if (prev == NULL) { pTable->descriptors = newDesc; } else { prev->next = newDesc; } /* 更新统计信息 */ regionCount++; totalMem += newDesc->size; if (newDesc->type == MEM_TYPE_RAM && !(newDesc->flags & MEM_FLAG_RESERVED)) { usableMem += newDesc->size; } prev = newDesc; current = current->next; } /* 设置表信息 */ pTable->numRegions = regionCount; pTable->totalMemory = totalMem; pTable->usableMemory = usableMem; pTable->initialized = TRUE; semGive(pTable->lock); return OK; }

2.3 物理内存分配器设计与实现

2.3.1 伙伴系统(Buddy System)分配器

VxWorks使用改进的伙伴系统管理物理内存页框分配,在碎片和效率之间取得平衡:

/* 伙伴系统数据结构 */ #define MAX_ORDER 11 /* 最大阶数,支持最大块为2^11=2048页 */ typedef struct buddy_system { UINT32 totalPages; /* 总页数 */ UINT32 freePages; /* 空闲页数 */ UINT32 minOrder; /* 最小分配阶数 */ UINT32 maxOrder; /* 最大分配阶数 */ LIST freeLists[MAX_ORDER + 1]; /* 各阶空闲链表 */ UINT8 *pageMap; /* 页状态位图 */ SEM_ID lock; /* 分配器锁 */ UINT32 allocCount; /* 分配次数统计 */ UINT32 freeCount; /* 释放次数统计 */ } BUDDY_SYSTEM; /* 页框结构 */ typedef struct page_frame { PHYS_ADDR physAddr; /* 物理地址 */ UINT32 order; /* 所属块的大小阶数 */ UINT32 index; /* 在位图中的索引 */ struct page_frame *buddy; /* 伙伴指针 */ LIST_NODE listNode; /* 链表节点 */ } PAGE_FRAME; /* 伙伴系统初始化 */ STATUS buddyInit(BUDDY_SYSTEM *buddy, PHYS_ADDR start, PHYS_ADDR end) { UINT32 totalPages, i; UINT8 *pageMap; /* 计算总页数 */ totalPages = (end - start + 1) / PAGE_SIZE; /* 分配页状态位图 */ pageMap = (UINT8 *)malloc((totalPages + 7) / 8); if (pageMap == NULL) { return ERROR; } memset(pageMap, 0, (totalPages + 7) / 8); /* 初始化伙伴系统结构 */ buddy->totalPages = totalPages; buddy->freePages = totalPages; buddy->minOrder = 0; /* 最小1页 */ buddy->maxOrder = 0; /* 计算最大阶数 */ while ((1U << buddy->maxOrder) <= totalPages && buddy->maxOrder < MAX_ORDER) { buddy->maxOrder++; } buddy->maxOrder--; /* 调整到实际最大阶数 */ /* 初始化各阶空闲链表 */ for (i = 0; i <= buddy->maxOrder; i++) { lstInit(&buddy->freeLists[i]); } /* 初始化锁 */ buddy->lock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE); if (buddy->lock == NULL) { free(pageMap); return ERROR; } buddy->pageMap = pageMap; buddy->allocCount = 0; buddy->freeCount = 0; /* 将所有内存作为单个大块插入最大阶空闲链表 */ PAGE_FRAME *firstBlock = createPageFrame(start, buddy->maxOrder, 0); if (firstBlock == NULL) { free(pageMap); semDelete(buddy->lock); return ERROR; } lstAdd(&buddy->freeLists[buddy->maxOrder], &firstBlock->listNode); return OK; } /* 页框分配函数 */ PAGE_FRAME *buddyAlloc(BUDDY_SYSTEM *buddy, UINT32 order) { UINT32 currentOrder; PAGE_FRAME *block, *buddyBlock; if (order > buddy->maxOrder) { return NULL; } semTake(buddy->lock, WAIT_FOREVER); /* 从请求的阶数开始查找 */ currentOrder = order; while (currentOrder <= buddy->maxOrder) { if (!lstEmpty(&buddy->freeLists[currentOrder])) { /* 找到合适块,从链表移除 */ block = (PAGE_FRAME *)lstFirst(&buddy->freeLists[currentOrder]); lstDelete(&buddy->freeLists[currentOrder], &block->listNode); /* 如果块比需要的大,进行分裂 */ while (currentOrder > order) { currentOrder--; /* 创建伙伴块 */ buddyBlock = splitBlock(block, currentOrder); if (buddyBlock == NULL) { semGive(buddy->lock); return NULL; } /* 将伙伴块插入对应阶的空闲链表 */ lstAdd(&buddy->freeLists[currentOrder], &buddyBlock->listNode); } /* 标记页为已分配 */ markPagesAllocated(buddy, block, order); buddy->freePages -= (1 << order); buddy->allocCount++; semGive(buddy->lock); return block; } currentOrder++; } semGive(buddy->lock); return NULL; /* 内存不足 */ } /* 页框释放函数 */ STATUS buddyFree(BUDDY_SYSTEM *buddy, PAGE_FRAME *frame) { UINT32 order = frame->order; PAGE_FRAME *buddyFrame; if (frame == NULL) { return ERROR; } semTake(buddy->lock, WAIT_FOREVER); /* 标记页为未分配 */ markPagesFree(buddy, frame, order); /* 尝试与伙伴合并 */ while (order < buddy->maxOrder) { buddyFrame = findBuddy(buddy, frame, order); if (buddyFrame == NULL || !isFree(buddy, buddyFrame, order)) { break; /* 伙伴不存在或已分配,停止合并 */ } /* 从空闲链表中移除伙伴 */ lstDelete(&buddy->freeLists[order], &buddyFrame->listNode); /* 合并块 */ if (frame->physAddr > buddyFrame->physAddr) { PAGE_FRAME *temp = frame; frame = buddyFrame; buddyFrame = temp; } /* 释放伙伴块结构 */ freePageFrame(buddyFrame); order++; /* 合并后块大小增加一阶 */ } /* 将合并后的块插入对应阶的空闲链表 */ frame->order = order; lstAdd(&buddy->freeLists[order], &frame->listNode); buddy->freePages += (1 << order); buddy->freeCount++; semGive(buddy->lock); return OK; }

2.3.2 物理内存池管理器

针对频繁的小块物理内存分配需求,VxWorks实现了一个物理内存池管理器:

/* 物理内存池结构 */ typedef struct phys_mem_pool { char name[16]; /* 池名称 */ PHYS_ADDR baseAddr; /* 池基地址 */ UINT32 blockSize; /* 块大小(对齐到页大小) */ UINT32 blockCount; /* 块总数 */ UINT32 freeCount; /* 空闲块数 */ UINT32 *freeStack; /* 空闲块栈 */ UINT32 stackTop; /* 栈顶指针 */ SEM_ID lock; /* 池锁 */ UINT32 allocCount; /* 分配计数 */ UINT32 freeCountTotal; /* 释放计数 */ } PHYS_MEM_POOL; /* 创建物理内存池 */ PHYS_MEM_POOL *physPoolCreate(const char *name, PHYS_ADDR base, UINT32 blockSize, UINT32 blockCount) { PHYS_MEM_POOL *pool; UINT32 i; if (name == NULL || base == 0 || blockSize == 0 || blockCount == 0) { return NULL; } /* 分配池控制结构 */ pool = (PHYS_MEM_POOL *)malloc(sizeof(PHYS_MEM_POOL)); if (pool == NULL) { return NULL; } /* 初始化池信息 */ strncpy(pool->name, name, sizeof(pool->name) - 1); pool->name[sizeof(pool->name) - 1] = '\0'; pool->baseAddr = base; pool->blockSize = ALIGN_UP(blockSize, PAGE_SIZE); pool->blockCount = blockCount; pool->freeCount = blockCount; /* 分配空闲块栈 */ pool->freeStack = (UINT32 *)malloc(blockCount * sizeof(UINT32)); if (pool->freeStack == NULL) { free(pool); return NULL; } /* 初始化空闲块栈(后进先出,提高缓存命中率) */ for (i = 0; i < blockCount; i++) { pool->freeStack[i] = i; /* 存储块索引 */ } pool->stackTop = blockCount - 1; /* 创建保护锁 */ pool->lock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE); if (pool->lock == NULL) { free(pool->freeStack); free(pool); return NULL; } pool->allocCount = 0; pool->freeCountTotal = 0; return pool; } /* 从物理内存池分配块 */ PHYS_ADDR physPoolAlloc(PHYS_MEM_POOL *pool) { UINT32 blockIndex; PHYS_ADDR blockAddr; if (pool == NULL) { return 0; } semTake(pool->lock, WAIT_FOREVER); if (pool->freeCount == 0) { semGive(pool->lock); return 0; /* 池已空 */ } /* 从栈顶获取空闲块索引 */ blockIndex = pool->freeStack[pool->stackTop]; pool->stackTop--; pool->freeCount--; pool->allocCount++; /* 计算块物理地址 */ blockAddr = pool->baseAddr + (blockIndex * pool->blockSize); semGive(pool->lock); return blockAddr; } /* 释放块到物理内存池 */ STATUS physPoolFree(PHYS_MEM_POOL *pool, PHYS_ADDR blockAddr) { UINT32 blockIndex; if (pool == NULL || blockAddr == 0) { return ERROR; } /* 验证地址在池范围内 */ if (blockAddr < pool->baseAddr || blockAddr >= pool->baseAddr + pool->blockCount * pool->blockSize) { return ERROR; } /* 计算块索引 */ blockIndex = (blockAddr - pool->baseAddr) / pool->blockSize; semTake(pool->lock, WAIT_FOREVER); if (pool->freeCount >= pool->blockCount) { semGive(pool->lock); return ERROR; /* 不应发生:释放过多块 */ } /* 将块索引压入空闲栈 */ pool->stackTop++; pool->freeStack[pool->stackTop] = blockIndex; pool->freeCount++; pool->freeCountTotal++; semGive(pool->lock); return OK; }

2.4 地址映射架构与MMU管理

2.4.1 虚拟地址空间布局

VxWorks采用灵活的虚拟地址空间布局策略,支持多种处理器架构:

典型的ARM架构虚拟地址空间布局(32位): 0xFFFF FFFF ┌─────────────────────────────┐ │ 高端内存映射 │ │ 设备I/O、ROM、Flash等 │ 0xF000 0000├─────────────────────────────┤ │ 内核空间 │ │ 内核代码、数据、堆栈 │ 0xC000 0000├─────────────────────────────┤ │ 用户空间(可选) │ │ 应用程序代码和数据 │ 0x8000 0000├─────────────────────────────┤ │ 共享内存区域 │ │ 进程间通信、多核共享 │ 0x4000 0000├─────────────────────────────┤ │ 任务私有空间 │ │ 各任务独立地址空间 │ 0x0000 0000└─────────────────────────────┘

地址空间配置参数

/* config.h 中的地址空间配置 */ #define VM_KERNEL_BASE_ADRS 0xC0000000 /* 内核空间基地址 */ #define VM_KERNEL_SIZE 0x40000000 /* 内核空间大小:1GB */ #define VM_USER_BASE_ADRS 0x80000000 /* 用户空间基地址 */ #define VM_USER_SIZE 0x40000000 /* 用户空间大小:1GB */ #define VM_SHARED_BASE_ADRS 0x40000000 /* 共享空间基地址 */ #define VM_SHARED_SIZE 0x40000000 /* 共享空间大小:1GB */ #define VM_TASK_BASE_ADRS 0x00000000 /* 任务私有空间基地址 */ #define VM_TASK_SIZE 0x40000000 /* 任务私有空间大小:1GB */ /* 页表配置 */ #define VM_PAGE_SIZE 4096 /* 页大小 */ #define VM_L1_PAGE_TABLE_ENTRIES 4096 /* 一级页表项数 */ #define VM_L2_PAGE_TABLE_ENTRIES 256 /* 二级页表项数 */

2.4.2 多级页表管理

VxWorks针对不同处理器架构实现相应的页表管理机制:

/* ARM架构页表管理 */ #ifdef CPU_ARM /* ARM页表项定义 */ typedef struct arm_pte { union { struct { UINT32 type : 2; /* 页表项类型 */ UINT32 buffer : 1; /* 缓冲位 */ UINT32 cache : 1; /* 缓存位 */ UINT32 ap : 2; /* 访问权限 */ UINT32 tex : 3; /* 类型扩展 */ UINT32 apx : 1; /* 扩展访问权限 */ UINT32 s : 1; /* 共享位 */ UINT32 ng : 1; /* 非全局位 */ UINT32 base : 20; /* 物理页基地址 */ } bits; UINT32 value; }; } ARM_PTE; /* ARM页表管理结构 */ typedef struct arm_mmu { ARM_PTE *l1Table; /* 一级页表(4096项) */ ARM_PTE **l2Tables; /* 二级页表指针数组 */ UINT32 l1TablePhys; /* 一级页表物理地址 */ UINT32 l2TableCount; /* 二级页表数量 */ SEM_ID lock; /* 页表操作锁 */ BOOL enabled; /* MMU使能标志 */ } ARM_MMU; /* ARM MMU初始化 */ STATUS armMmuInit(ARM_MMU *mmu) { UINT32 i; if (mmu == NULL) { return ERROR; } /* 分配一级页表(16KB,4096项 * 4字节) */ mmu->l1Table = (ARM_PTE *)malloc(VM_L1_PAGE_TABLE_ENTRIES * sizeof(ARM_PTE)); if (mmu->l1Table == NULL) { return ERROR; } /* 获取一级页表物理地址 */ mmu->l1TablePhys = virtToPhys(mmu->l1Table); /* 分配二级页表指针数组 */ mmu->l2Tables = (ARM_PTE **)calloc(VM_L1_PAGE_TABLE_ENTRIES, sizeof(ARM_PTE *)); if (mmu->l2Tables == NULL) { free(mmu->l1Table); return ERROR; } /* 初始化所有一级页表项为无效 */ for (i = 0; i < VM_L1_PAGE_TABLE_ENTRIES; i++) { mmu->l1Table[i].value = 0; } mmu->l2TableCount = 0; mmu->lock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE); mmu->enabled = FALSE; return OK; } /* 建立虚拟地址到物理地址映射 */ STATUS armMmuMap(ARM_MMU *mmu, VIRT_ADDR virt, PHYS_ADDR phys, UINT32 size, UINT32 flags) { UINT32 virtPage, physPage; UINT32 numPages; UINT32 i, l1Index, l2Index; ARM_PTE *l2Table; if (mmu == NULL || size == 0) { return ERROR; } /* 地址对齐检查 */ if ((virt & (PAGE_SIZE - 1)) != 0 || (phys & (PAGE_SIZE - 1)) != 0) { return ERROR; } numPages = (size + PAGE_SIZE - 1) / PAGE_SIZE; semTake(mmu->lock, WAIT_FOREVER); for (i = 0; i < numPages; i++) { virtPage = virt + i * PAGE_SIZE; physPage = phys + i * PAGE_SIZE; /* 计算页表索引 */ l1Index = (virtPage >> 20) & 0xFFF; /* 12位一级索引 */ l2Index = (virtPage >> 12) & 0xFF; /* 8位二级索引 */ /* 检查一级页表项 */ if (mmu->l1Table[l1Index].bits.type == 0) { /* 一级页表项无效,需要分配二级页表 */ l2Table = (ARM_PTE *)malloc(256 * sizeof(ARM_PTE)); if (l2Table == NULL) { semGive(mmu->lock); return ERROR; } /* 初始化二级页表 */ memset(l2Table, 0, 256 * sizeof(ARM_PTE)); /* 设置一级页表项指向二级页表 */ mmu->l1Table[l1Index].bits.type = 1; /* 粗页表 */ mmu->l1Table[l1Index].bits.base = virtToPhys(l2Table) >> 10; mmu->l2Tables[l1Index] = l2Table; mmu->l2TableCount++; } else if (mmu->l1Table[l1Index].bits.type == 1) { /* 粗页表已存在 */ l2Table = mmu->l2Tables[l1Index]; } else { /* 其他类型(段或细页表),暂不支持 */ semGive(mmu->lock); return ERROR; } /* 设置二级页表项 */ l2Table[l2Index].bits.type = 2; /* 小页(4KB) */ l2Table[l2Index].bits.base = physPage >> 12; /* 设置页属性 */ if (flags & VM_PROT_READ) l2Table[l2Index].bits.ap = 0x3; if (flags & VM_PROT_WRITE) l2Table[l2Index].bits.ap = 0x3; if (flags & VM_PROT_EXECUTE) l2Table[l2Index].bits.ap = 0x3; if (flags & VM_PROT_DEVICE) { l2Table[l2Index].bits.cache = 0; l2Table[l2Index].bits.buffer = 0; } else { l2Table[l2Index].bits.cache = 1; l2Table[l2Index].bits.buffer = 1; } if (flags & VM_PROT_SHARED) { l2Table[l2Index].bits.s = 1; } } semGive(mmu->lock); /* 刷新TLB */ asm volatile("mcr p15, 0, %0, c8, c7, 0" : : "r" (0)); asm volatile("dsb"); asm volatile("isb"); return OK; } #endif /* CPU_ARM */

2.4.3 地址转换与查找

/* 地址转换工具函数 */ PHYS_ADDR virtToPhys(VIRT_ADDR virt) { /* 简单的线性映射示例 */ #ifdef LINEAR_MAPPING return virt - VM_KERNEL_BASE_ADRS; #else /* 实际实现需要查询页表 */ ARM_MMU *mmu = getCurrentMmu(); UINT32 l1Index, l2Index; ARM_PTE *l2Table; PHYS_ADDR phys; if (mmu == NULL || !mmu->enabled) { return virt; /* MMU未启用,虚拟地址等于物理地址 */ } l1Index = (virt >> 20) & 0xFFF; l2Index = (virt >> 12) & 0xFF; if (mmu->l1Table[l1Index].bits.type != 1) { return 0; /* 无效映射 */ } l2Table = mmu->l2Tables[l1Index]; if (l2Table[l2Index].bits.type != 2) { return 0; /* 无效映射 */ } phys = (l2Table[l2Index].bits.base << 12) | (virt & 0xFFF); return phys; #endif } VIRT_ADDR physToVirt(PHYS_ADDR phys) { /* 反向线性映射 */ #ifdef LINEAR_MAPPING return phys + VM_KERNEL_BASE_ADRS; #else /* 实际实现需要反向查找页表,效率较低 */ /* 通常只在调试时使用 */ ARM_MMU *mmu = getCurrentMmu(); UINT32 i, j; if (mmu == NULL || !mmu->enabled) { return phys; } /* 遍历所有页表项查找匹配的物理地址 */ for (i = 0; i < VM_L1_PAGE_TABLE_ENTRIES; i++) { if (mmu->l1Table[i].bits.type == 1) { ARM_PTE *l2Table = mmu->l2Tables[i]; for (j = 0; j < 256; j++) { if (l2Table[j].bits.type == 2) { PHYS_ADDR pagePhys = l2Table[j].bits.base << 12; if (pagePhys == (phys & ~0xFFF)) { return (i << 20) | (j << 12) | (phys & 0xFFF); } } } } } return 0; /* 未找到映射 */ #endif }

2.5 多核内存管理机制

2.5.1 核间内存同步与一致性

/* 多核内存管理结构 */ typedef struct multi_core_mem { UINT32 coreCount; /* 核心数量 */ PHYS_ADDR perCoreBase; /* 每核私有内存基地址 */ UINT32 perCoreSize; /* 每核私有内存大小 */ PHYS_ADDR sharedBase; /* 共享内存基地址 */ UINT32 sharedSize; /* 共享内存大小 */ CACHE_COHERENCY *coherency; /* 缓存一致性控制器 */ SEM_ID *coreLocks; /* 每核内存分配锁 */ BOOL initialized; /* 初始化标志 */ } MULTI_CORE_MEM; /* 缓存一致性管理 */ typedef struct cache_coherency { UINT32 type; /* 一致性协议类型 */ void *regBase; /* 寄存器基地址 */ UINT32 lineSize; /* 缓存行大小 */ UINT32 wayCount; /* 路数 */ SEM_ID lock; /* 操作锁 */ /* 维护函数指针 */ STATUS (*invalidateRange)(void *addr, UINT32 size); STATUS (*cleanRange)(void *addr, UINT32 size); STATUS (*flushRange)(void *addr, UINT32 size); } CACHE_COHERENCY; /* 多核内存分配器 */ typedef struct multi_core_allocator { BUDDY_SYSTEM *globalBuddy; /* 全局伙伴系统 */ BUDDY_SYSTEM **perCoreBuddies; /* 每核伙伴系统 */ PHYS_MEM_POOL *globalPool; /* 全局内存池 */ PHYS_MEM_POOL **perCorePools; /* 每核内存池 */ UINT32 coreCount; /* 核心数量 */ SEM_ID globalLock; /* 全局分配锁 */ } MULTI_CORE_ALLOCATOR; /* 多核感知的内存分配 */ void *multiCoreAlloc(MULTI_CORE_ALLOCATOR *allocator, UINT32 size, UINT32 flags) { UINT32 coreId = getCoreId(); void *memory = NULL; if (allocator == NULL) { return NULL; } /* 根据标志选择分配策略 */ if (flags & MC_ALLOC_LOCAL) { /* 分配本地内存(当前核私有) */ if (allocator->perCorePools != NULL && allocator->perCorePools[coreId] != NULL) { memory = (void *)physPoolAlloc(allocator->perCorePools[coreId]); } } else if (flags & MC_ALLOC_SHARED) { /* 分配共享内存 */ semTake(allocator->globalLock, WAIT_FOREVER); if (size <= PAGE_SIZE && allocator->globalPool != NULL) { memory = (void *)physPoolAlloc(allocator->globalPool); } else if (allocator->globalBuddy != NULL) { UINT32 order = sizeToOrder(size); PAGE_FRAME *frame = buddyAlloc(allocator->globalBuddy, order); if (frame != NULL) { memory = (void *)frame->physAddr; } } semGive(allocator->globalLock); } /* 如果分配了内存,确保缓存一致性 */ if (memory != NULL && (flags & MC_ALLOC_SHARED)) { CACHE_COHERENCY *cc = getCacheCoherency(); if (cc != NULL && cc->flushRange != NULL) { cc->flushRange(memory, size); } } return memory; }

2.5.2 核间通信内存

/* 核间通信内存管理 */ typedef struct ipc_memory { PHYS_ADDR base; /* 物理基地址 */ VIRT_ADDR virt; /* 虚拟地址 */ UINT32 size; /* 总大小 */ UINT32 slotSize; /* 每个槽大小 */ UINT32 slotCount; /* 槽数量 */ SEM_ID *slotLocks; /* 槽访问锁 */ UINT8 *slotStatus; /* 槽状态位图 */ UINT32 producerCore; /* 生产者核心ID */ UINT32 consumerCore; /* 消费者核心ID */ } IPC_MEMORY; /* 创建核间通信内存 */ IPC_MEMORY *ipcMemCreate(UINT32 totalSize, UINT32 slotSize) { IPC_MEMORY *ipc; UINT32 i, slotCount; if (totalSize == 0 || slotSize == 0) { return NULL; } slotCount = totalSize / slotSize; /* 分配IPC内存结构 */ ipc = (IPC_MEMORY *)malloc(sizeof(IPC_MEMORY)); if (ipc == NULL) { return NULL; } /* 分配物理内存 */ ipc->base = physAllocContiguous(totalSize, PAGE_SIZE); if (ipc->base == 0) { free(ipc); return NULL; } /* 映射到虚拟地址空间 */ ipc->virt = vmMap(NULL, ipc->base, totalSize, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_SHARED); if (ipc->virt == 0) { physFree(ipc->base, totalSize); free(ipc); return NULL; } ipc->size = totalSize; ipc->slotSize = slotSize; ipc->slotCount = slotCount; /* 分配槽锁数组 */ ipc->slotLocks = (SEM_ID *)malloc(slotCount * sizeof(SEM_ID)); if (ipc->slotLocks == NULL) { vmUnmap(ipc->virt, totalSize); physFree(ipc->base, totalSize); free(ipc); return NULL; } /* 初始化每个槽的锁 */ for (i = 0; i < slotCount; i++) { ipc->slotLocks[i] = semBCreate(SEM_Q_FIFO, SEM_FULL); if (ipc->slotLocks[i] == NULL) { /* 清理已创建的锁 */ for (UINT32 j = 0; j < i; j++) { semDelete(ipc->slotLocks[j]); } free(ipc->slotLocks); vmUnmap(ipc->virt, totalSize); physFree(ipc->base, totalSize); free(ipc); return NULL; } } /* 初始化槽状态位图 */ ipc->slotStatus = (UINT8 *)calloc((slotCount + 7) / 8, 1); if (ipc->slotStatus == NULL) { for (i = 0; i < slotCount; i++) { semDelete(ipc->slotLocks[i]); } free(ipc->slotLocks); vmUnmap(ipc->virt, totalSize); physFree(ipc->base, totalSize); free(ipc); return NULL; } ipc->producerCore = 0xFFFFFFFF; /* 未指定 */ ipc->consumerCore = 0xFFFFFFFF; /* 未指定 */ return ipc; }

2.6 内存保护与权限管理

2.6.1 内存保护域

/* 内存保护域结构 */ typedef struct mem_protection_domain { UINT32 domainId; /* 域ID */ char name[16]; /* 域名 */ UINT32 accessRights; /* 访问权限位图 */ LIST regionList; /* 保护区域链表 */ SEM_ID lock; /* 域锁 */ UINT32 refCount; /* 引用计数 */ } MEM_PROTECTION_DOMAIN; /* 内存保护区域 */ typedef struct protected_region { VIRT_ADDR start; /* 起始虚拟地址 */ VIRT_ADDR end; /* 结束虚拟地址 */ UINT32 size; /* 区域大小 */ UINT32 permissions; /* 权限位 */ UINT32 domainId; /* 所属域ID */ LIST_NODE listNode; /* 链表节点 */ } PROTECTED_REGION; /* 内存访问权限检查 */ BOOL checkMemoryAccess(UINT32 coreId, VIRT_ADDR addr, UINT32 accessType) { MEM_PROTECTION_DOMAIN *domain; PROTECTED_REGION *region; UINT32 coreDomainId; /* 获取当前核心的保护域 */ coreDomainId = getCoreDomainId(coreId); domain = getProtectionDomain(coreDomainId); if (domain == NULL) { return FALSE; /* 核心无保护域,拒绝访问 */ } semTake(domain->lock, WAIT_FOREVER); /* 查找包含该地址的保护区域 */ region = (PROTECTED_REGION *)lstFirst(&domain->regionList); while (region != NULL) { if (addr >= region->start && addr < region->end) { /* 检查权限 */ BOOL allowed = (region->permissions & accessType) != 0; semGive(domain->lock); return allowed; } region = (PROTECTED_REGION *)lstNext(&region->listNode); } semGive(domain->lock); /* 地址不在任何保护区域内,使用默认策略 */ return (domain->accessRights & accessType) != 0; }

2.7 总结

物理内存管理与地址映射机制是VxWorks内存管理的基石,它直接与硬件交互,为上层提供可靠的内存服务。本部分深入分析了:

  1. 物理内存探测与初始化:系统启动阶段如何发现和建立内存映射

  2. 物理内存分配算法:伙伴系统和内存池的实现细节

  3. 地址映射架构:多级页表管理和MMU配置

  4. 多核内存管理:核间同步、缓存一致性和通信内存

  5. 内存保护机制:访问权限控制和保护域

这些机制共同确保了VxWorks在嵌入式实时环境中的确定性、可靠性和性能。在第三部分中,我们将深入探讨动态内存分配算法与实现细节,包括系统堆管理、内存池优化和碎片整理策略。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询