1. 多核SMP架构与VxWorks演进

1.1 从单核到多核:调度问题的本质变化

在单核VxWorks系统中,调度器的核心任务非常清晰:在任意时刻,CPU上只能运行一个任务,调度算法只需在就绪队列中选出优先级最高的任务并切换上下文。Wind内核采用基于优先级的抢占式调度,256个优先级(0最高,255最低),同优先级任务可选时间片轮转。此时“并发”只是宏观上的假象,微观上任务严格串行执行,共享数据的竞争仅发生在任务与中断之间。

进入多核时代后,情况发生了根本性变化。假设一个四核处理器上同时有4个高优先级任务就绪,它们可以真正并行运行。这带来三个新的调度挑战:

  • 任务放置问题:新创建或唤醒的任务应该放到哪个CPU的就绪队列?是固定绑定还是动态迁移?
  • 负载均衡问题:当某个CPU空闲而另一个CPU积压多个就绪任务时,如何把任务“搬”过去?搬运的时机和频率如何控制?
  • 数据一致性成本:多核并行访问共享数据结构(如就绪队列、调度器锁)时,必须用自旋锁或原子操作保护,这些同步开销会随核数增加而放大。

因此,多核调度不是单核调度的简单复制,而是要在“并行收益”与“同步开销”之间做权衡。

1.2 SMP对称多处理基本模型

SMP(Symmetric Multiprocessing,对称多处理)的核心特征是:所有CPU核在硬件上对等,共享同一物理内存空间和同一份操作系统映像,每个核都能访问全部外设和中断控制器。与之相对的是AMP(非对称多处理),每个核运行独立的OS实例,核间通过共享内存或消息通信。

在SMP模型中,VxWorks内核维护一个全局就绪队列集合,每个CPU有各自的本地就绪队列,同时存在一个全局调度器锁来保护关键区。任务可以在任意CPU上运行,也可以被迁移。中断可以被路由到指定CPU,但同一中断源通常只由一个CPU处理,以避免中断嵌套的复杂性。

需要特别注意的是,SMP下“优先级”的含义没有改变,但“最高优先级任务”可能同时有多个实例在不同核上运行。因此,调度器必须保证:任何时刻,每个CPU上运行的任务优先级都不低于该CPU就绪队列中的其他任务;同时,全局最高优先级任务必须至少在一个CPU上运行。

VxWorks SMP 对称多处理架构模型 CPU 0 本地就绪队列 T1(prio 5) T3(prio 12) CPU 1 本地就绪队列 T2(prio 5) T4(prio 20) CPU 2 本地就绪队列 T5(prio 8) CPU 3 本地就绪队列 空闲 全局调度器锁 (Spinlock) 保护就绪队列、任务迁移、负载均衡 共享物理内存 (SMP 统一地址空间) 全局就绪队列 · 任务控制块 · 内核对象 · 设备驱动 负载均衡器 (Load Balancer) 周期性检查各CPU负载 → 从高负载CPU迁移任务到空闲CPU → 迁移时需获取全局调度器锁 CPU核 同步锁 共享内存 就绪队列

1.3 VxWorks 7 SMP关键特性与硬件抽象层要求

VxWorks 7对SMP的支持不是简单打补丁,而是从内核到BSP的体系化重构。其关键特性包括:

  • 统一内核映像:所有CPU核运行同一份VxWorks内核,通过CPU索引(cpuIndex)区分当前核,避免AMP下多份映像的维护负担。
  • 细粒度锁与无锁数据结构:内核对象(任务、信号量、消息队列)的锁粒度被细化,部分只读路径采用RCU或原子操作,减少核间争用。
  • CPU亲和性(Affinity):任务可绑定到指定CPU集合,适合缓存局部性敏感或需要隔离关键任务的场景。默认不绑定,允许迁移。
  • 中断亲和性:外部中断可路由到指定CPU,避免所有中断集中在一个核上形成瓶颈。
  • 核间中断(IPI):用于触发远程CPU的调度、TLB刷新、缓存一致性维护等操作。

硬件抽象层(HAL)必须满足以下要求才能支撑SMP:

  • 提供原子指令(如LDREX/STREX、CAS)用于实现自旋锁和引用计数。
  • 提供内存屏障指令(DMB/DSB/ISB),保证多核间的内存访问顺序。
  • 提供每核私有存储(如TPIDRPRW寄存器)用于存放cpuIndex和当前任务指针。
  • 中断控制器支持IPI分发和中断亲和性配置(如GIC-400的SPI/PPI路由)。
  • 启动时完成从核(secondary core)的唤醒与初始化,主核负责引导并释放从核进入调度循环。

1.4 一个可观察的调度场景

假设四核VxWorks 7系统上运行以下任务(优先级数值越小越高):

任务优先级CPU亲和性状态
T_high_A5CPU0就绪
T_high_B5CPU1就绪
T_mid12无绑定就绪
T_low20无绑定就绪

初始时,CPU0运行T_high_A,CPU1运行T_high_B,CPU2和CPU3空闲。负载均衡器发现CPU2/3空闲,而T_mid和T_low在全局就绪队列中等待,于是将T_mid迁移到CPU2,T_low迁移到CPU3。此时四个核都在运行任务,系统吞吐量提升。若T_high_A阻塞(如等待信号量),CPU0会立即从本地或全局队列选取下一个最高优先级任务,可能是T_mid(如果它未被绑定且仍在CPU0队列中)。

这个场景说明:SMP调度的核心不是“让每个核都忙”,而是“让最高优先级任务尽快获得CPU,同时控制迁移和锁的开销”。实际工程中,可以通过VxWorks的taskCpuAffinitySet()设置亲和性,通过spawn或taskSpawn的选项控制任务初始CPU,并通过kernelTimeSlice调整同优先级轮转时间片。

实践提示:在调试SMP调度问题时,优先使用ti(task info)查看各任务当前所在CPU和状态,使用spy或windView观察任务迁移和核间负载分布。若发现某个核长期空闲而其他核积压,应检查任务亲和性是否过度绑定,以及全局调度器锁的争用计数是否异常升高。

1.5 本章小结

从单核到多核,VxWorks的调度挑战从“选哪个任务”扩展为“选哪个任务、放哪个核、何时迁移、如何同步”。SMP对称多处理模型通过共享内存和统一内核映像获得并行能力,但代价是锁竞争和缓存一致性开销。VxWorks 7通过细粒度锁、CPU亲和性、IPI和HAL原子指令支持,使SMP调度在实时性和吞吐量之间取得平衡。理解这些基础,是后续分析多核调度延迟、优先级反转和性能瓶颈的前提。