4. 分区间通信机制与工程实现

在 ARINC 653 分区化航电系统中,分区之间在时间与空间上被严格隔离,一个分区无法直接访问另一个分区的内存。分区之间要交换数据,必须通过由分区操作系统(POS)统一管理的通信端口。ARINC 653 Part 1 定义了两种分区端口:Sampling Port(采样端口)与Queuing Port(队列端口)。理解这两种端口的语义差异,并正确配置其属性,是分区间通信工程实现的核心。

一、两种端口的语义差异

Sampling Port 是“状态型”通信:发送方把消息写入端口后,端口只保留最新一份消息,接收方读取时得到的是当前最新值。如果接收方读取速度慢于发送方,中间的历史消息会被覆盖丢弃。它适合传输“当前状态”类数据,例如大气数据计算机输出的当前高度、姿态角、空速等——接收方关心的是最新值,而不是历史序列。

Queuing Port 是“消息型”通信:端口内部维护一个 FIFO 队列,发送方每写一条消息就入队,接收方按顺序逐条出队。队列有固定容量(最大消息数)和固定最大消息长度,队列满时发送方会阻塞或返回错误,队列空时接收方会阻塞或返回错误。它适合传输“事件/指令”类数据,例如告警事件、离散指令、需要逐条处理的报文。

两者的关键区别可以概括为:Sampling 是“覆盖式、读最新”,Queuing 是“排队式、按序取”。选择哪种端口,取决于数据语义是状态还是事件。

Sampling Port 与 Queuing Port 通信语义对比 Sampling Port(采样端口) 状态型 · 只保留最新值 · 覆盖旧值 发送分区 写消息 端口缓冲 仅存最新 1 条 接收 分区 发送序列: M1 M2 M3 → 覆盖 接收方读到: M3 (M1、M2 已被覆盖) 典型数据: 高度、姿态角、空速、位置等 周期性刷新的状态量 Queuing Port(队列端口) 消息型 · FIFO 排队 · 按序取 发送分区 写消息 FIFO 队列 容量 N 条 满则阻塞/报错 接收 分区 发送序列: M1 M2 M3 → 入队 接收方按序读到: M1 M2 M3 典型数据: 告警事件、离散指令、逐条报文 不可丢失、需按序处理的消息

二、端口属性配置

在 ARINC 653 的 XML 配置文件中,每个端口都需要声明一组属性。Sampling Port 的关键属性包括:MaxMessageSize(最大消息字节数)、Direction(SOURCE 或 DESTINATION)、RefreshPeriod(刷新周期,用于周期调度)。Queuing Port 的关键属性包括:MaxMessageSize、MaxNbMessage(队列最大消息数)、Direction、Discipline(排队规则,通常为 FIFO)。

一个常见的工程配置片段如下(示例参数,非实测值):

<SamplingPort Name="ADIRU_Altitude" Direction="DESTINATION"
              MaxMessageSize="16" RefreshPeriod="20">
  <Source PartitionName="ADIRU" PortName="Altitude_Out"/>
</SamplingPort>

<QueuingPort Name="Warning_Events" Direction="SOURCE"
             MaxMessageSize="64" MaxNbMessage="32" Discipline="FIFO">
  <Destination PartitionName="DISPLAY" PortName="Warning_In"/>
</QueuingPort>

这里 RefreshPeriod="20" 表示该采样端口按 20 ms 周期刷新,接收分区在每个周期读取一次最新值;MaxNbMessage="32" 表示队列最多缓存 32 条告警消息,超过后发送方将阻塞或返回 NO_ACTION 错误。配置时必须保证发送方与接收方的 MaxMessageSize 一致,否则会出现截断或配置校验失败。

三、分区内与分区间消息传递

分区内通信通常使用缓冲区(Buffer)或黑板(Blackboard),它们由分区内部管理,不跨分区边界。分区间通信则必须通过 Sampling/Queuing Port,由 POS 在分区切换时完成数据搬运。工程上要特别注意:分区间端口的读写发生在分区时间窗口内,发送方写入后,接收方要等到自己的时间窗口才能读取,因此存在一个调度周期量级的延迟。

以两个分区 A(发送)和 B(接收)为例,若 A 在 0 ms 写入采样端口,B 的窗口在 10 ms 开始,则 B 在 10 ms 读到该值;若 A 在 15 ms 又写入新值,B 在 20 ms 读到的是 15 ms 的值。这种“最新值”语义正是 Sampling Port 的设计意图。

四、通信服务调用

ARINC 653 为端口操作定义了一组标准服务调用。Sampling Port 常用服务:WRITE_SAMPLING_MESSAGE、READ_SAMPLING_MESSAGE。Queuing Port 常用服务:SEND_QUEUING_MESSAGE、RECEIVE_QUEUING_MESSAGE、GET_QUEUING_MESSAGE_STATUS。这些服务在分区内以 API 形式调用,返回值用于判断操作是否成功。

RETURN_CODE_TYPE ret;
MESSAGE_SIZE_TYPE len;

/* 采样端口写:写入最新高度值 */
WRITE_SAMPLING_MESSAGE(altitude_port, &alt_msg, &len, &ret);
if (ret != NO_ERROR) { /* 处理错误 */ }

/* 队列端口收:按序取一条告警 */
RECEIVE_QUEUING_MESSAGE(warning_port, 0, &warn_msg, &len, &ret);
if (ret == NO_ACTION) { /* 队列为空 */ }

注意 RECEIVE_QUEUING_MESSAGE 的第二个参数是超时时间(0 表示不等待)。若队列为空且超时为 0,返回 NO_ACTION;若队列满时发送,返回 NO_ACTION 或阻塞,取决于配置。工程中应始终检查返回码,避免静默丢消息。

五、调试与验证要点

调试分区间通信时,建议按以下顺序排查:第一,确认端口名称、方向、消息长度在发送方与接收方配置中完全匹配;第二,确认分区时间窗口已正确分配,接收方窗口晚于发送方写入时刻;第三,用 GET_QUEUING_MESSAGE_STATUS 观察队列当前消息数与最大容量,判断是否发生溢出;第四,对 Sampling Port,检查 RefreshPeriod 是否与分区周期协调,避免读到过期值。

调试小技巧:在接收分区中周期性打印端口状态(消息数、最新值时间戳),可以快速区分“没发”“发了没收到”“收到了但被覆盖”三类问题。对于 Queuing Port,若持续出现队列满,应优先检查接收方处理速度或增大 MaxNbMessage。

综上,Sampling Port 与 Queuing Port 分别对应“状态”与“事件”两种通信语义。工程实现的关键在于:根据数据语义选对端口类型,严格对齐双方属性配置,理解分区调度带来的读写时序,并在服务调用中正确处理返回码。掌握这些要点,才能构建可靠的分区间通信链路。