SOME/IP 协议介绍(三)参数和数据结构的序列化

参数和数据结构的序列化

序列化是基于接口规范定义的参数列表。为了允许服务接口的迁移,反序列化,代码应忽略附加在先前已知的参数列表末尾的参数;也就是说,忽略在用于生成或参数化反序列化代码的接口规范中未定义的参数。

接口规范定义了PDU中所有参数的确切位置,并考虑了内存对齐。序列化过程不应尝试自动对齐参数,而应按照接口规范中指定的对齐方式进行对齐。SOME/IP负载应该在内存中放置,以使SOME/IP负载能够适当地对齐。对于车载娱乐设备的ECU,应该实现8字节(即64位)的对齐,对于所有ECU,至少应实现4字节的对齐。
接下来将指定不同参数的反序列化过程。

基本数据类型

应支持以下基本数据类型:

Type

Description

Size [bit]

Remark

boolean

TRUE/FALSE value

8

FALSE (0), TRUE (1)

uint8

unsigned Integer

8

uint16

unsigned Integer

16

uint32

unsigned Integer

32

sint8

signed Integer

8

sint16

signed Integer

16

sint32

signed Integer

32

float32

floating point number

32

IEEE 754 binary32 (Single Precision)

float64

floating point number

64

IEEE 754 binary64 (Double Precision)

每个参数的字节顺序由接口定义进行规定。

结构化数据类型 (结构体)

结构体的序列化应尽可能接近内存布局。这意味着参数应按顺序序列化到缓冲区中。对于结构体来说,特别要考虑正确的内存对齐。如果需要对齐,请在接口定义中插入保留/填充元素,因为SOME/IP实现不会自动添加此类填充。

如果SOME/IP实现遇到导致PDU未正确对齐的接口规范(例如,由于未对齐的结构体),SOME/IP实现应在发现不对齐的结构体时发出警告,但不应在生成代码时失败。
结构体的序列化应按照规范精确地进行。
SOME/IP实现不应自动插入虚拟/填充元素。

SOME/IP 协议介绍(三)参数和数据结构的序列化_第1张图片

接口规范可以在结构体前面添加一个8位、16位或32位的长度字段。如果未指定长度字段的长度,则必须假定长度为0,并且消息中没有长度字段。

结构体的长度字段描述了结构体的字节数。如果长度大于接口定义中指定的结构体长度,则只有接口规范中指定的字节将被解释,其他字节将根据长度字段被跳过。这样可以实现可扩展的结构体,从而更好地实现接口的迁移。

字符串(定长)

字符串使用Unicode进行编码,并以“\0”字符结尾。在接口定义中必须指定字符串的字节长度(包括“\0”)。使用“\0”填充未使用的空间。
应支持不同的Unicode编码,包括UTF-8、UTF-16BE和UTF-16LE。由于这些编码每个字符的字节长度是动态的,字节的最大长度是UTF-8中字符长度的三倍加上1个字节的“\0”终止符,或者UTF-16中字符长度的两倍加上2个字节的“\0”终止符。
字符串的编码方式应在接口定义中指定。

字符串(动态长度)

动态长度的字符串以长度字段开头。长度以字节为单位,并跟随以“\0”结尾的字符串数据。接口定义还应定义字符串(包括以“\0”结尾)可以占用的最大字节数。
长度字段的长度可以是8位、16位或32位。固定长度的字符串可以视为长度字段为0位。
如果接口规范没有另外指定,长度字段的长度为32位(长度字段的默认长度)。
字符串长度字段的值不考虑在长度字段本身的值中;也就是说,长度字段不计入自身的长度。
支持的编码方式如[SIP_RPC_232第19页]中所定义。
如果接口定义提示下一个数据元素的对齐方式,字符串应通过添加“\0”字符来扩展以满足对齐要求。

数组(固定长度)

固定长度数组的长度由接口定义确定。它们可以被视为重复的元素。在[SIP_RPC_253 页错误!未定义书签。]中展示了动态长度数组,也可以使用。然而,固定长度数组可以更容易地集成到早期版本的AUTOSAR和非常小的设备中;因此,两种选项都得到支持。

一维数组

固定长度为n的一维数组包含恰好n个相同类型的元素。布局如图2所示。

SOME/IP 协议介绍(三)参数和数据结构的序列化_第2张图片

多维数组

多维数组的序列化遵循C++编程语言中多维数组的内存布局(按行主序),如图3所示

SOME/IP 协议介绍(三)参数和数据结构的序列化_第3张图片

可选字段

可选字段应被编码为包含0到1个元素的数组。对于具有动态长度的数组的序列化,请参阅[SIP_RPC_253]。
动态长度数组
具有动态长度的数组的布局基本上基于固定长度数组的布局。为了确定数组的大小,序列化在数据前面添加一个长度字段(默认长度为32位),该字段计算数组的字节数。长度不包括长度字段的大小。因此,在传输零元素的数组时,长度设置为零。
接口定义可以定义长度字段的长度。允许长度为0、8、16和32位。如果将长度设置为0位,则数组中的元素数量必须是固定的;因此,它是具有固定长度的数组。

动态数组的布局如图4和图5所示。

SOME/IP 协议介绍(三)参数和数据结构的序列化_第4张图片

在一维数组中,使用一个长度字段,该字段表示数组使用的字节数。可以通过将字节数除以元素的大小来轻松计算元素的数量。

SOME/IP 协议介绍(三)参数和数据结构的序列化_第5张图片

在多维数组中,需要多个长度字段。接口定义应定义每个维度的最大长度,以便允许进行静态缓冲区大小的分配。在以字节为单位测量长度时,可以在反序列化过程中跳过复杂的多维数组。

枚举

接口定义可以基于无符号整数数据类型(uint8、uint16、uint32、uint64)指定枚举类型。

位域

位域应作为基本数据类型uint8/uint16/uint32进行传输。接口定义应能够定义每个位的名称。接口定义应能够定义位可以设置为的值的名称。
每个SOME/IP实现可以选择对位域进行解/序列化,或者将uint8/uint16/uint32传递给应用程序。SOME/IP实现可以允许开启或关闭位域的解/序列化。

联合(变体)

联合(也称为变体)是一种可以包含不同类型元素的参数。例如,如果定义了一个uint8类型和uint16类型的联合,该联合将携带一个uint8或uint16类型的元素。显然,当使用不同类型的元素时,后续参数的对齐可能会被扭曲。为了解决这个问题,可能需要填充。
默认情况下,SOME/IP中联合的序列化布局如下:

SOME/IP 协议介绍(三)参数和数据结构的序列化_第6张图片


长度字段和类型字段的顺序可以通过接口规范进行调整。如果未指定,则使用[TR_SOMEIP_00119]中的默认布局。

长度字段的长度应由接口规范定义,并且可以是32位、16位、8位或0位。长度字段为0位表示不会将长度字段写入PDU。如果长度字段为0位,则联合中的所有类型的长度必须相同。

如果接口规范定义了一个长度字段为0位的联合,并且具有不同长度的类型,则SOME/IP实现应该发出警告,并使用最长元素的长度,并用零(0x00)填充其他元素。
如果接口规范未指定联合的长度字段的长度,则应使用32位长度的长度字段。
长度字段以字节为单位定义元素和填充的大小,不包括长度字段和类型字段的大小。

类型字段的长度应由接口规范定义,并且可以是32位、16位或8位。
如果接口规范未指定联合的类型字段的长度,则应使用32位长度的类型字段。
类型字段描述元素的类型。类型字段的可能值由接口规范为每个联合单独定义。类型按照接口规范中的编码以升序排列,从1开始。0保留为NULL类型,即空联合。接口定义应允许使用NULL。

根据类型字段中的类型,元素将进行序列化。结合长度字段,可以在元素后面添加填充。反序列化器应根据长度字段跳过字节。每种类型的长度字段的值应由接口规范定义。通过使用结构体,可以实现不同的填充布局。

示例:uint8/uint16联合,均填充为32位

在此示例中,长度字段的长度指定为32位。该联合应支持uint8和uint16作为元素。两者都填充到32位边界(长度为4)。uint8的序列化如下所示:

SOME/IP 协议介绍(三)参数和数据结构的序列化_第7张图片

uint16的序列化如下所示:

SOME/IP 协议介绍(三)参数和数据结构的序列化_第8张图片

将映射或字典描述为键值对数组是最基本的方式。实现映射或字典的最基本方法是使用一个具有两个字段(键和值)的结构体数组。由于结构体没有长度字段,这种方式与特殊的映射或字典类型一样高效。如果选择uint16作为键和值,一个包含3个条目的序列化映射如下所示:

SOME/IP 协议介绍(三)参数和数据结构的序列化_第9张图片


SOME/IP 协议介绍(三)参数和数据结构的序列化_第10张图片

你可能感兴趣的:(SOME/IP,tcp/ip,数据结构,网络协议)