Files

12 KiB
Raw Permalink Blame History

分区 RTOS:INTEGRITY / ARINC 653 / VxWorks 653 / PikeOS

这类系统的调度**不止一层**:
分区级调度(major frame / partition window / budget)
        ↓
分区内调度(进程/任务优先级,本分区自己的调度器)

于是最常见的误判是:

Task A priority = 250,Task B = 100
B 在跑,A 完全没运行
  → 不是"调度器坏了",也不是 starvation
  → A 可能处在当前没有执行窗口/预算的分区里

"高优先级线程没运行"在这里首先是分区级的解释,然后才是任务级的解释。 </CORE RULE>

一、两层调度与 major frame

  • 分区级:固定、循环、离线定义的调度。分区在一个循环区间内被周期性释放一段时间
  • 这个区间叫 major time frame(MAF),由若干 partition window 组成;每个窗口由时长、偏移、周期性定义
  • 激活顺序在配置表里静态定义,运行期不可更改;设计良好时 MAF 时长 ≈ 各分区周期的最小公倍数
  • 分区调度表列出相对 MAF 起点的抢占点;调度就是"当前时钟落在某分区的窗口内(偏移 → 偏移+时长)"
  • 分区内:由分区自己的调度器管理其进程(ARINC 653 语境下通常是固定优先级抢占式)

分析要求:时间线必须先在分区级对齐,再谈线程级。

二、分区模式:进程"不跑"常常是还没进 NORMAL

ARINC 653 的分区有四态:IDLE / COLD_START / WARM_START / NORMAL

模式 含义
COLD_START 初始化进行中;抢占被锁定;应用在跑初始化代码;初始环境可能需要从非易失存储器把代码拷到 RAM
WARM_START 也是初始化且抢占锁定,但初始环境与冷启动可以不同(例如不需要从 NVM 拷代码)
NORMAL 初始化完成,分区的进程调度器活跃,已创建的就绪进程可以运行
IDLE 没有进程在执行,但分配给该分区的窗口仍保留
  • 迁移关系:IDLE → COLD/WARM_START;COLD_START → NORMAL;NORMAL → COLD/WARM_START(重启);→ IDLE(关机/设为 IDLE)
  • 服务:SET_PARTITION_MODE 与 GET_PARTITION_STATUS(返回标识、周期、时长、锁层级、运行模式、启动条件)
  • 初始化模式(COLD/WARM_START)下只有主进程可调度;错误处理程序在初始化阶段创建,并可调用 SET_PARTITION_MODE 重启分区

所以:

CREATE_PROCESS() / START() 都做了,但进程一直不跑
  → 先查是否执行了 SET_PARTITION_MODE(NORMAL)
  → 而不是立即判调度器损坏

三、采样端口与队列端口:语义不同,不能混

采样端口(sampling) 队列端口(queuing)
缓冲 单条消息 可配置的消息条数
覆盖 新消息覆盖旧消息,应用总是读到最新的 不覆盖,按 FIFO 传送
丢消息 可能丢/被覆盖 不丢;队列满时发送失败/阻塞
刷新周期 只对采样模式的接收有意义(判断是否有新消息到达) 不适用
  • channel 把一个源端口连到一个或多个目的端口;分区之间由内核强制内存保护,其他分区无法访问本分区的端口

所以:

连续写了 A B C,最后只读到 C
  → 对采样端口可能完全正常
  → 对队列端口则不正常

四、INTEGRITY:空间 + 时间 + 资源三域分区

  • 微内核架构,支持多个受保护的虚拟地址空间,每个可含多个应用任务;用硬件 MMU 建立隔离
  • 完整的分区包含空间、时间与资源三个域;失败不会跨分区传播
  • 固定预算:可为每个进程分配固定的 CPU 时间与内存预算;保证时间窗也意味着运行中的任务不会超出其窗口
  • 其他机制:实时调度器支持多优先级与完整的 CPU 百分比分配控制;内核服务时间有界;内核空间不做动态内存分配;内置 ARINC 653 Part 1 分区调度器(带保证的执行时间窗);内存配额系统防止一个地址空间耗尽另一个的内存;内核内存不用于消息、信号量等由进程请求创建的对象
  • 静态配置:架构师预先写好静态配置文件,定义分区、任务集、内存对象、链接、连接通道、时钟与分区调度机制;启动表定义归属;连接静态分配且不可绕过;MMU 设置可静态验证
  • 多核:不同分区时间窗内可绑定到不同核;共享资源争用可使 WCET 增加 8–13 倍(这也是相关适航指导强调的)

RE 主线:

CPU 明明还有空闲,应用却拿不到更多执行时间
  → 可能是预算隔离(设计如此),不是调度效率 bug

五、PikeOS:还有第三层

PikeOS 是第二代分离微内核(同时是 hypervisor):静态循环调度分区(时间隔离)+ 内存区(空间隔离);每个分区有自己的调度结构,支持 256 个优先级;系统分区与当前活动分区同时被调度以提供系统服务。

POSIX guest 的层次:

PikeOS 分区/资源调度器
        ↓
PikeOS system thread(每核一个可供该 POSIX 内核使用)
        ↓
POSIX guest 内核自己的调度器
        ↓
POSIX 用户线程
  • POSIX 内核自己的调度器把它的用户线程映射到一个 PikeOS system thread;许多 POSIX 驱动还会自建 I/O 线程
  • POSIX guest 实现的是 PSE52 子集,加上实时与 PikeOS 专有扩展(包含 ARINC 653 采样/队列端口)
  • APEX guest:完整实现 ARINC 653 P1-5 与部分 P2-4(分区管理、健康监控、采样/队列端口、进程管理、分区内通信与同步、logbook、文件系统、内存块、服务访问点端口)
  • APEX 服务经一张链接在固定地址的 API table 进入:开发时应用与库及链接脚本给出的 API 服务表地址链接
  • 初始化完成后 APEX 内核把控制交给用户提供的 MAIN(),起始于 COLD_START(抢占锁定、创建静态资源),之后分区转入 NORMAL(进程调度器活跃、完整 APEX API 可用)

两条推论:

guest 内线程是最高优先级,但延迟突然到 10 ms
  → 不能只看 pthread 调度器:查当前分区是否有执行窗口、
    对应 system thread 是否可运行、CPU affinity/分区调度是什么

看到大量 ldr x16, [固定基址+偏移]; blr x16
  → 先查是否是 APEX 服务表,而不是控制流混淆

六、Deos:两级调度 + slack + SafeMC

  • 时间/空间/资源分区的安全关键 RTOS(DAL A 认证):分区允许把不同设计保证等级的软件混跑在同一处理器上,并提供故障隔离与应用重启
  • 两级调度模型(SafeMC 明确描述):
Level 1:时间被划分为在各核之间【对齐】的执行窗口
Level 2:每个核/window 指派具体 scheduler
          ├─ ARINC 653
          ├─ Deos RMA(速率单调)
          └─ POSIX
应用被指派给一个或多个 scheduler;每个 scheduler 可跨多个 process/partition 调度多个 task
  • 同一颗核在不同时间段可以跑不同调度规律(window 1 用 ARINC 653、window 2 用 POSIX、window 3 用 RMA 是这套架构能表达的)——trace 里调度规律切换不能自动判调度器状态损坏
  • Slack Scheduling(滑动时间窗):窗口可以压缩、扩张、滑动——分区提前完成可压缩窗口,需要更多时间且有空闲可扩张,也可以让他人提前或延后开始。所以"budget 给了 10 ms、任务只用了 6 ms,另一个任务拿到剩余 CPU"不是时间分区逃逸,而是 slack 回收;CPU 接近 100% 也可以仍在预算内
  • Cache partitioning:软件实现、可配置,把缓存隔离做到应用/分区级(不只是核级),免去分区切换时的 cache flush(那会影响 WCET),并与**内存池(memory pooling)**互补(控制应用落在物理内存的哪里)
  • 开发工具本身也可能利用 slack time 做通信/profiling/monitoring 以少干扰关键负载——trace 里"应用执行 → 一小段工具流量 → 应用执行"先确认是不是这个
  • 多核用 BMP(SMP 的扩展)+ 安全调度 + 缓存分区 + 内存池 限制共享资源干扰。任务 READY、CPU 也有,但执行被多核策略约束,不一定是普通调度决策——要恢复 core assignment / window / cache partition / memory pool / 跨核干扰策略
  • 也可以承载其他环境:例如某 para-virtualized RTOS 实现运行在它的安全分区里,对外提供 POSIX 接口——看到 pthread_* 不代表脱离了 Deos 分区控制
  • 两个不同安全分区能看到共享内存也不等于隔离被破坏:应查是否配置为共享、权限、谁可写、生命周期
  • 若观测到 major frame 起点缓慢漂移:Deos 提供外部时钟同步类能力(本次核验未直接命中上游资料,作为候选解释之一并在具体型号文档上确认),不要直接判 timer drift 或 trace 时钟坏了

排错顺序(重要):

Task 没运行
 → 属于哪个 process/partition?
 → 在哪个 core?
 → 当前 window 是否 active?
 → window 内是什么 scheduler?
 → 本地优先级/状态?
 → budget?
 → SafeMC 限制?
 → 才看 deadlock/bug

对这类系统,配置与分区调度表优先于反汇编猜内部调度器——公开文档未必开放全部内核细节。

同族系统

决策树

拿到分区 RTOS 目标
├─ 先分层:分区级调度 vs 分区内调度
│    ├─ 对齐 major frame / partition window(时长、偏移、周期)
│    └─ 再谈进程/任务优先级
├─ 高优先级线程不运行
│    ├─ 查它所属分区当前是否有执行窗口
│    ├─ 查分区模式(是否还在 COLD/WARM_START,未进 NORMAL)
│    └─ 查资源/时间预算是否已耗尽(故意的隔离)
├─ 通信异常
│    ├─ 采样端口:覆盖语义,"只读到最新"属正常
│    └─ 队列端口:FIFO、不覆盖,满则失败/阻塞
├─ 看到固定地址函数表
│    └─ 先考虑 APEX 服务表一类的 ABI,不要直接判混淆
└─ 多核 / 性能归因
     └─ 把共享资源争用与预算隔离算进去(WCET 可能显著放大)

工具与验证

  • 调度:分区调度表 / 时间窗配置、MAF 与窗口参数、分区模式状态
  • 资源:分区/进程的 CPU 时间与内存配额、静态配置文件与启动表
  • 通信:端口类型(采样/队列)与各自参数
  • 验证:能同时说清「分区级时间窗 + 分区内调度结果 + 预算/模式状态」,三者缺一不能解释"为什么没跑"

该平台的坑(汇总)

  • 用统一的优先级队列解释调度:至少两层(PikeOS 场景是三层)
  • 把"高优先级线程不跑"当 starvation 或调度器 bug:先看分区窗口与预算
  • 忽略分区模式:COLD/WARM_START 下只有主进程可调度,进程当然"不跑"
  • 把采样端口当队列端口:覆盖语义下"只读到最新"是正常的
  • 把队列端口当采样端口:消息不会互相覆盖,丢失就一定是问题
  • 把资源/时间预算隔离当性能缺陷:固定预算是隔离机制的一部分
  • 只逆 guest 内容:PikeOS 一类系统里 guest 调度器不是最终调度器
  • 把固定地址的 APEX 服务表当控制流混淆
  • 多核分析忽略共享资源争用:WCET 可能成倍放大