EPICS V7 解析(三) - pvAccess协议编码

pvAccess协议数据编码

1. 协议概述

pvAccess协议是一种用于分布式系统通信的协议,支持高效的数据序列化与反序列化。其数据编码设计强调灵活性、高效性和跨平台兼容性,支持多种数据类型(标量、数组、结构、联合等),并通过元数据(如内省数据、位集)实现动态类型管理和部分序列化优化。

2. 数据编码规则

2.1 大小(Size)编码

规则:

  • 空值(Null):用单字节0xFF表示。
  • 元素数 < 254:直接以1字节无符号整数编码。
  • 元素数 < 2³¹-1:首字节0xFE,后接32位有符号整数。
  • 元素数 ≥ 2³¹-1:暂不支持,但预留扩展方案(首字节0xFE,后接0x7FFFFFFF及64位整数)。

限制:最大支持元素数为2⁶³-1,但实际实现受限于协议版本。

2.2 字节序处理

  • 连接导向协议(如TCP)需通过SET_ENDIANESS控制消息协商字节序,而非依赖消息头的字节序标志。

  • 无连接协议(如UDP)由发送方决定字节序,接收方需自适应解析。

3. 基本类型编码

类型编码方式
布尔值1字节(0为false,非零为true,发送方无需统一非零值)。
整数二补码表示(8/16/32/64位),如byte(8位)、short(16位)。
无符号整数直接二进制表示,如ubyte(8位)、ulong(64位)。
浮点数遵循IEEE-754标准(float为32位单精度,double为64位双精度)。

4. 复合类型编码

4.1 数组

  • 可变数组:大小+元素序列(如03 01 02 03)。

  • 有界数组:大小≤预设上限(如byte<16>最多16元素)。

  • 固定数组:无需大小字段,严格按定义长度解析(如byte[4]必须4元素)。

4.2 字符串

  • 编码为UTF-8字节数组,前置大小字段(字节数,非字符数)。

  • 有界字符串:大小不得超过预设界限,编码方式与普通字符串相同。

  • 禁止终止符:内部实现若使用\0,序列化时需剔除。

4.3 结构体(Structure)

按字段定义顺序依次编码各成员。

结构数组:每个元素前加存在标志(0x00表示空,0x01后接结构数据)。

示例:

结构体数组[{0x1111, 0x2222}, null, {0x3333, 0x4444}]编码为:
03 01 11 11 22 22 00 01 33 33 44 44

4.4 联合(Union)与变体联合(Variant Union)

  • 普通联合:编码为选择器值(size类型)后接所选成员数据。

  • 变体联合:编码为内省描述(Field类型)后接实际数据,支持开放类型。

5. 元数据编码

5.1 位集(BitSet)

编码方式:按8位组序列化,低位优先(LSB到MSB),优化传输时剔除尾部零。

示例:

{8}:编码为02 00 013字节,表示第8位为1)。


{0,1,2,4}:编码为01 17(二进制00010111)。

5.2 部分结构序列化

通过位集标记序列化的字段,仅传输变更部分。

位分配规则:结构体内每个字段对应一个位,若父结构位被设置,则所有子字段必须序列化。

6. 状态(Status)编码

标准结构:

struct Status {

  byte type;       // 枚举:OK(0), WARNING(1), ERROR(2), FATAL(3)

  string message;  // 可选错误信息 
  string callTree; // 调用栈信息(可选)

};

优化:若状态为OK且无附加信息,可简化为StatusOK结构(单字节0xFF)。

示例:

StatusOK:FF


WARNING, "Low memory", ""01 0A 4C 6F 77 20 6D 65 6D 6F 72 79 00

7. 内省数据(Introspection Data)

7.1 编码类型

类型码描述
NULL_TYPE_CODE无内省数据(单字节0xFF)。
ONLY_ID_TYPE_CODE仅发送类型ID(0xFE后接ID)。
FULL_WITH_ID_TYPE_CODE发送ID及完整类型描述(0xFD后接ID及字段描述)。
FULL_TAGGED_ID_TYPE_CODE含ID、标签及类型描述(0xFC后接ID、标签及描述)。

7.2 动态类型管理

ID分配:发送方动态分配短整型ID,接收方缓存ID与类型描述的映射。

复用优化:首次发送使用完整描述,后续使用ID减少数据量。

示例:

时间戳结构体的内省数据编码(部分):
FD 00 01 80 0B 74 69 6D 65 53 74 61 6D 70 5F 74 ...

8. 示例分析

8.1 结构体编码示例

给定结构体:

structure {

byte[] value [1,2,3];

byte<16> boundedSizeArray [4,5,6,7,8];

byte[4] fixedSizeArray [9,10,11,12];

// …嵌套结构体及联合
}

编码结果:

03 01 02 03 05 04 05 06 07 08 09 0A 0B 0C ...

03:可变数组大小(3元素)

05:有界数组大小(5元素)

固定数组直接编码4元素。

8.2 内省数据示例

复杂结构体的内省数据通过FULL_WITH_ID_TYPE_CODE编码,包含类型ID、字段名称及嵌套结构描述。

9. 协议实现注意事项

字节序协商:TCP连接需通过控制消息协商字节序,而非依赖消息头标志。

大小限制:当前不支持≥2³¹-1元素的数组,需预留扩展接口。

内省数据缓存:接收方需维护类型ID映射表以支持复用。

性能优化:利用部分序列化(位集标记)减少数据传输量。

10. 总结

pvAccess协议通过灵活的数据编码机制和元数据管理,实现了高效、可扩展的通信能力。其设计特点包括:

类型自描述:内省数据支持动态类型解析。

传输优化:位集标记和部分序列化减少冗余数据传输。

跨平台兼容:明确的字节序协商和标准编码规则(如IEEE-754)。

未来改进方向可包括支持更大规模数据集、增强内省数据的版本兼容性,以及进一步优化变体联合的解析效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值