1. 共享内存基础:VxWorks SMP架构概述、共享内存的概念与原理、物理内存与虚拟内存映射
好,咱们开始第一讲。共享内存,说白了就是让多个核能看见同一块数据。这个概念听起来简单,但实际用起来坑不少。我做了这么多年嵌入式,见过太多因为共享内存没处理好导致系统崩溃的案例。今天咱们就把这个基础打牢。
1.1 VxWorks SMP架构概述
SMP,对称多处理。什么意思?就是所有CPU核心地位平等,共享同一份内存空间,跑同一个操作系统。你想想看,四个核就像四个工人,都在同一个车间里干活,工具(内存)是共用的。
在VxWorks SMP系统中,每个核都有自己的寄存器组和缓存,但物理内存是统一的。系统启动时,VxWorks会检测到有多少个核可用,然后统一调度任务到各个核上运行。
核心特点:
- 所有核共享同一个内存地址空间
- 操作系统统一管理所有核
- 任务可以在任意核上调度执行
- 核间通过共享内存和中断通信
我记得刚接触SMP时,总觉得多核就是多个单核拼一起。后来踩了坑才发现,事情没那么简单。核间缓存一致性问题、任务迁移的开销、锁竞争,这些都是SMP特有的麻烦。
1.2 共享内存的概念与原理
共享内存,就是一块可以被多个进程或线程同时访问的内存区域。在VxWorks中,共享内存通常用于核间通信(IPC)和数据交换。
为什么会需要共享内存?我给你举个例子。假设核0采集了传感器数据,核1要做数据处理。如果没有共享内存,你就得用消息队列或者管道来传数据。但消息队列有拷贝开销,数据量大时性能很差。共享内存就不一样了,数据写进去,另一个核直接读,零拷贝。
我的经验:在项目中,如果数据交换频率高、数据量大,我一般优先考虑共享内存。消息队列适合小数据量、低频次的通信。
共享内存的工作原理其实不复杂:
- 一块物理内存被映射到多个进程的地址空间
- 一个进程写数据,另一个进程直接看到变化
- 需要同步机制(如信号量)来防止数据竞争
嗯,这里要注意:共享内存本身不提供同步机制。你写我读,如果不同步,读到的可能是半成品数据。我曾经在一个项目中,两个核共享一个结构体,没加锁,结果读到的数据总是错乱的。排查了两天才发现问题。
1.3 物理内存与虚拟内存映射
这个知识点,很多初学者容易搞混。物理内存是硬件上真实存在的内存条。虚拟内存是每个进程看到的假想地址空间。VxWorks通过MMU(内存管理单元)把虚拟地址翻译成物理地址。
在SMP系统中,所有核共享同一个物理内存。但每个核的虚拟地址空间是独立的吗?不一定。VxWorks中,内核空间是所有核共享的,用户空间则取决于配置。
| 概念 | 说明 | 我踩过的坑 |
|---|---|---|
| 物理地址 | 硬件内存的真实地址 | 直接操作物理地址要小心,容易崩系统 |
| 虚拟地址 | CPU看到的地址,经过MMU转换 | 不同进程的虚拟地址相同,但物理地址不同 |
| 映射关系 | 虚拟→物理的对应表 | 映射错了,写数据会写到奇怪的地方 |
在VxWorks中,共享内存的创建通常涉及以下步骤:
/* 分配物理连续内存 */
PHYS_MEM_ADDR physAddr = cacheDmaMalloc(size);
/* 将物理内存映射到虚拟地址空间 */
void *virtAddr = (void *)vmMap(NULL, physAddr, size,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE,
VM_STATE_VALID | VM_STATE_WRITABLE);
/* 其他核通过相同物理地址映射 */
void *otherVirtAddr = (void *)vmMap(NULL, physAddr, size,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE,
VM_STATE_VALID | VM_STATE_WRITABLE);
警告:共享内存的物理地址必须对所有核可见。有些平台的内存区域是核私有的,比如某些ARM核的TCM(紧耦合内存),不能用作共享内存。
我个人习惯在项目初期就把物理内存布局画清楚。哪块内存给核0用,哪块给核1用,哪块是共享的。画清楚了,后面少很多麻烦。
还有一个容易忽略的点:缓存一致性。当核0写共享内存时,数据可能还在自己的缓存里,没有刷回主存。核1去读主存,读到的是旧数据。解决办法是使用缓存一致性协议(如MESI),或者手动刷缓存。
/* 写共享内存后,刷缓存 */
CACHE_FLUSH(sharedAddr, size);
/* 读共享内存前,使缓存失效 */
CACHE_INVALIDATE(sharedAddr, size);
我曾经在一个项目中,就是因为忘了刷缓存,两个核之间通信总是丢数据。查了三天,最后发现是缓存没刷。从那以后,我写共享内存代码,第一件事就是加上缓存操作。
小结
这一章咱们讲了三个核心概念:SMP架构、共享内存原理、物理虚拟内存映射。说白了,共享内存就是让多核能高效交换数据的手段。但高效是有代价的——你得处理好同步、缓存一致性和地址映射这些细节。
下一章,咱们会深入讲共享内存的创建和配置,包括VxWorks提供的API和实际代码示例。到时候我会拿一个真实项目中的例子来讲解,保证你能用得上。