本文主要是开源的vsomeip项目的<<vsomeip in 10 minutes >>进行简单的翻译,原文网址:https://github.com/GENIVI/vsomeip/wiki/vsomeip-in-10-minutes
文章目录
1.SOME/IP Introduction
1.1SOME/IP Short Introduction
SOME/IP是Scalable service-Oriented middlewarE over IP的缩写,意思是:基于IP的可拓展的面向服务的中间件。该中间件设计之初就是用于汽车,并且其被AUTOSAR所兼容(至少在wire-format层面是兼容的)。我们可以在http://some-ip.com/访问到公开的SOME/IP相关知识。本篇文章不想对SOME/IP进行详细的描述,只是对SOME/IP规范的进行简单描述以及其部分的介绍其开源实现vsomeip。
SOME/IP有以下三个重要的特性:
- On-wire format
- Protocol Service
- Discovery
1.1.1.SOME/IP On-Wire Format
在IP中,SOME/IP通信由设备或者subscribers之间的message构成,如下图所示:
图中A和B代表两个设备:设备A向设备B发送了一条SOME/IP message,然后设备B返回一条message。在该过程中,底层使用的协议可以是TCP或者UDP,但是不管使用的是哪一种协议,其包含的SOME/IP message都是一样的。假设设备B作为service提供服务,那么该过程就是:客户端A就是访问B中服务,之后B返回一个answer。
SOME/IP messages含有两部分:header and payload。上图中,可以发现header 包含的信息有:
- Service ID:服务的ID,每一个服务的ID都需要是唯一的
- Method ID:0-32767用于methods, 32768-65535用于 events
- Length:该字段之后内容的长度,以字节为单位。(包含其后的其他ID,即payload+8bytes)
- Client ID:ECU中调用服务的客户端的ID号,需要在整个汽车中唯一
- Session ID:客户端和服务端的session handling标识符,客户端每调用一次服务端就Session ID就需要加1
- Protocol Version:0x01
- Interface Version:服务接口的主版本号
- Message Type:- REQUEST:0x00,request&response method中的request报文;- REQUEST_NO_RETURN:0x01,fire&forget method的request类型;- NOTIFICATION:0x02,被订阅的服务端向客户端进行单向的通知;- RESPONSE:0x80,request&response method中的response报文
- Return Code:- E_OK (0x00):没有错误产生;- E_NOT_OK (0x01):产生unspecified错误;- E_WRONG_INTERFACE_VERSION (0x08):接口版本不匹配;- E_MALFORMED_MESSAGE (0x09):payload反序列化失败;- E_WRONG_MESSAGE_TYPE (0x0A):message类型错误,例如:REQUEST报文被当作RESPONSE报文接收
在 header我们可以见到:正常的服务访问形式 “REQUESTs” 和"RESPONSEs",服务端对订阅了它的客户端进行事件通知,RESPONSE或NOTIFICATION类型的message包含错误信息。
payload中包含着经过序列化的数据。上图演示了一个简单的序列化例子:其数据结构中的数据都是基本类型,在序列化的时候只需要把其中数据一个接一个的放成连续的一列就行。
1.1.2.SOME/IP Protocol
该部分有两个重要的点:
- transport binding(UDP and TCP)
- 基本的通信方式:两两一组,分别是publish/subscribe和request/response
之前提到过底层通信协议使用的是UDP或者TCP。假如使用UDP,SOME/IP messages不用被拆开发送,一条UDP message中可能包含多条SOME/IP messages(每条SOME/IP messages的长度都不能超过单个UDP package,至多为1400 Bytes)。长度更长的SOME/IP messages必须用TCP协议进行传输。如果在使用TCP协议进行通信的时候发生synchronization error,SOME/IP 支持使用magic cookies从出错的地方重新发送message。
注意:service interface必须被实例化才能使用,并且考虑到同一个service interface可能有多个实例,所以需要再加一个标识符instance ID进行区分。instance ID并没有被包含在header中,而是与端口号有关:同一个service interface的多个实例使用不同的端口号进行服务提供,通过这些端口号来定义instance ID。
下图演示了基本的SOME/IP通信的方式:
remote procedure calls(RPC)除了标准的REQUEST/RESPONSE机制,还有用于 event的SOME/IP SD message。SOME/IP 中的经常多个event组成eventgroup来进行使用。 SOME/IP也有fields类型的接口,其包含的setter/getter和REQUEST/RESPONSE一样, notfierl类似PUBLISH,但是其中的subscription由其自身通过SOME/IP service discovery完成。
1.1.3.SOME/IP Service discovery
SOME/IP Service Discovery用于寻找服务,并判断该服务是否在运行以及是否是 Publish/Subscribe类型。其使用offer messages来实现上述的功能:网络中的每一个设备通过广播(或多播)的方式发出包含该设备提供的所有服务的message。SOME/IP SD messages只能通过UDP协议进行传播。如果客户端想要的服务没有被提供,那么客户端也会发送find messages去寻找服务。其他的SOME/IP SD message用于实现Publish/Subscribe。
下图演示了一般情况下的SOME/IP SD message报文架构:
可见,该报文就是一种包含特殊payload的SOME/IP报文。
2.vsomeip
2.1vsomeip Short Overview
GENIVI基于SOME/IP协议的实现就是vsomeip,其基本架构如下图:
如图所示,vsomeip不仅实现了 SOME/IP中两个设备间的通信,也实现了同个设备中的内部进程间通信。两个设备之间的通信通过 communication endpoint(该endpoint决定使用TCP还是UDP协议)实现的。设备内部的通信通过 local endpoints来实现,实际上是通过 unix domain socket机制实现的。因为内部通信不用通过central component(例如:D-Bus daemon)进行路由管理,所以传输速度非常快。
vsomeip内部的路由管理只有在message需要在两个设备间传输的时候才会起作用。一个机器上只会存在一个路由管理,如果不指定路由管理,那么第一个被启动的app就会被作为路由管理来使用。
注意:
vsomeip没有实现数据序列化的功能。序列化是通过SOME/IP绑定的CommonAPI实现的。vsomeip实现了SOME/IP protocol和the Service Discovery。
2.2.Preparation / Prerequisites
构建vsomeip之前,你需要确保你的电脑上已经安装了BOOST库(版本需要大于1.55)。构建步骤如下:
$ cd vsomeip
<.>/vsomeip$ mkdir build
<.>/vsomeip$ cd build
<.>/vsomeip/build$ cmake ..
<.>/vsomeip/build$ make
上述步骤就可以成功构建vsomeip,但是为了避免一些不必要的错误,我们需要对上述的cmake步进行如下修改:
<.>/vsomeip/build$ cmake -DENABLE_SIGNAL_HANDLING=1 ..
ENABLE_SIGNAL_HANDLING参数可以保证你真正的杀死你启动的进程(不加该参数可能会导致你按Ctral+C的时候,共享内存 /dev/shm/vsomeip并没有被真正的移除)。