仅靠增加内存和处理周期无法应对设计嵌入式系统(需满足对工业应用程序日益增长的需求)时面临的挑战。这些应用程序有三种特征是系统设计人员面临的严峻挑战:它们通常功能复杂并装有不同的设备和软件组件;必须支持复杂的人机界面;计算资源有限。
永久性发布/订阅 (PPS) 消息传递能简化嵌入式工业系统的设计。为验证这一论断的正确性,我们在 QNX智能家用能源管理系统(一种集成了大量组件的嵌入式工业参考应用程序)中启用了 PPS。我们的结论是,与较常见的异步消息传递和发送/接收/回复消息传递模型相比,这种消息传递范例更适用于此类系统。
异步消息传递
异步消息传递已众所周知并得到广泛应用, 在此不作赘述。它是许多系统的首选解决方案,但其本身的一些特征使其难以成为嵌入式系统(必须集成大量设备和软件组件)的最佳解决方案。
需要注意的是,在复杂的嵌入式工业应用程序中启用消息传递模型时,异步消息传递只是一种低级解决方案,因为它只会增加应用程序级的错误处理、端到端语义和缓冲管理的负担。也就是说,要设计一种采用异步消息传递的系统,设计人员还必须开发一种或多种协议以确保在所有应用程序中正确进行消息传递,因为他们必须保证这些应用程序在高负载条件下能获得足够的内存分配以进行消息缓冲。如果是设计简单的系统,这些任务可能无足轻重,但要是设计或升级复杂的系统,它们就会成为设计人员的梦魇。
发送/接收/回复
发送/接收/回复(同步)消息传递不如异步消息传递那样常见。它的重要性主要体现在实时环境中,因为那里的许多进程必须先响应消息后才能继续运行。此外,与异步消息传递不同的是,采用发送/接收/回复消息传递时,系统框架会承受处理消息传递错误和消息缓冲的负担。
但是,和异步消息传递一样,发送/接收/回复消息传递也不是复杂系统的首选,特别是当这些系统不仅要轻松兼容新设备,而且要在正常使用期内集成大量不同的程序和功能时。发送/接收/回复消息传递密切联系着发送方和接收方。每个服务器都与其客户端直接通信,而且必须知道如何响应所有客户端消息。由于消息传递的联系如此密切,因此更改一个软件组件可能需要更改其他软件组件,这不仅延缓或阻碍了系统开发,而且还加剧了系统的脆弱性。
依据初始连接要求设计和应用的解决方案在引入新要求时就显得捉襟见肘了。它们通常依赖于通信应用程序/组件之间直接、点对点的连接。总之,如果采用发送/接收/回复消息传递,当系统不断扩展并增加不同组件时,其复杂性会迅速加剧,而且会变得不堪一击,因此很难在确保性能和可靠性的同时进行升级和扩展。
------------------------------------------------------------------------------------------------
二进制对象还是可读对象?
PPS 服务可设计成使用二进制对象或可读对象。
我们选择将可读对象和属性用于 QNXPPS,因为与较大的对象相比,其具备更大的开发和调试优势。
可读对象允许使用简单的文件系统工具(如用于订阅的 cat 和用于发布的 echo)或使用简单程序(订阅一个对象并打印出包括PPS 对象和属性在内的调试信息)从命令行进行调试。
------------------------------------------------------------------------------------------------
永久性发布/订阅
发布/订阅已经以各种形式应用了至少 20 年。1987年,K.P.Birman 和 T.A.Joseph 将类似的消息传递模型(虚拟同步)描述为一种容错的异步公告牌机制。二十年前,北电网络公司(Nortel Networks)应用了一种类似模型以在电话交换机(如 DMS-100)上进行故障监测,还采用了网络监测和报告系统的技术。只要在网上快速搜索,就能找到许多发布/订阅的应用实例,再深入搜索,还能在美国计算机协会 (ACM) 的门户网站上找到几百份与发布/订阅的某些方面或其他 Observer 模式计算模型有关的文章。
我们将重点介绍在重启时也能确保发布/ 订阅模型(PPS)不仅能帮助各种设备和软件组件的应用程序开发和部署,而且这些应用程序还能与复杂的人机界面通信。
基于对象的系统
PPS 是在松耦合消息架构中针对发布者和订阅者提供的一种基于对象的服务。根据实现服务的需要,任何 PPS 服务客户端都可以是一个独立的发布者、订阅者,也可以既是发布者又是订阅者。
发布是以异步方式进行的。PPS 对象会集中到 PPS 文件系统的路径名空间内。发布者可修改对象及其属性并写入文件系统中。当任何发布者更改对象时,PPS 服务都会通知订阅该对象的所有客户端。PPS 客户端能订阅多个对象,PPS对象能有多个发布者和多个订阅者。因此,能访问不同对象属性应用数据的发布者可使用相同对象与该对象的所有订阅者交流信息。
PPS 客户端一定清楚自己对哪些 PPS 对象感兴趣。如果是发布者,它们必须了解在什么时候发布什么内容;如果是订阅者,它们必须了解要订阅的对象种类,以及感兴趣的对象属性。
PPS 客户端只需在使用 open()、read() 和 write() POSIXAPI 调用的范围内管理错误和缓冲,确认其理解读取的内容以及是否希望读取处于阻塞或非阻塞状态。PPS 服务会负责处理其他内容。客户端只需知道已读取消息并且能分析读取内容。同样,由于 PPS 订阅者使用 read() 调用检索对象,因此他们无需管理这些对象的缓冲区。理论上,订阅者能使用一个单字节缓冲区,并且能在读入其所需的全部内容以前一直读取。
------------------------------------------------------------------------------------------------
推送还是请求?
在默认状态下,QNX PPS 服务是作为推送式发布系统运行的;也就是说,发布者会将数据推送到对象中,订阅者会根据通知或在闲暇时读取数据。
但有些数据(如接口上的数据包计数)变化太快,因此无法通过使用默认推送发布的 PPS 有效地进行发布。
为此,QNX PPS 还提供一种选项,允许订阅者将PPS 变成请求式发布系统。当订阅者打开具有该选项的对象并发出一个 read() 调用时,该对象的所有发布者都会收到一个通知以在对象中写入当前数据。订阅者的读取会一直阻塞直至对象的数据得到更新并返回新的数据。
利用这种请求机制,PPS 订阅者能按其需要的速度向发布者检索数据,从而实现了真正意义上的按需发布。
------------------------------------------------------------------------------------------------
持久性
永久性发布/订阅服务能在重启时维护数据。它不仅能在运行时维护内存中的对象,而且能在运行时按需要或在关机时将对象保存到永久性存储体中。它能在系统启动时立即恢复或在首次访问(延迟加载)时恢复对象。当然,底层永久性存储体依赖于可靠的文件系统,如硬盘、NAND 或 NOR 闪存或其他定制文件系统。
除了能在重启时确保数据持久性以外,PPS 消息传递模型还能简化系统启动。例如,在使用另一种消息传递模式的系统中,如果客户端紧随服务器之后启动,那一定是该客户端向服务器请求最新数据,特别是在服务器和客户端启动之间的时间段内发生某些变化时。
当客户端与服务器失去联系(无论何种原因导致)时也会发出这种请求,系统中所有的客户端都会发出这样的请求,而且服务器必须做出响应。采用 PPS 时,系统服务会在启动时恢复对象并在其更改时进行维护。所有客户端(无论何时启动或重新连接)只需读取这些对象以获取最新数据即可。
------------------------------------------------------------------------------------------------
语言独立
PPS 服务既可设计成使用二进制,也可设计成使用标准 POSIX 文件系统服务的 QNX PPS,而且还能与所有编程语言或应用程序环境(包括 C、C++、Java、Javascript、ksh 脚本语言等)连用。
以一种语言编写的组件能与使用其他语言编写的组件通信。无需具备其他组件的专门知识。
------------------------------------------------------------------------------------------------
系统可扩展性
采用 PPS 时,发布者和订阅者互不相识,他们唯一的联系是具有某种含义和用途的对象。这种模型为设计系统的开发人员提供了极大的灵活性:必要时,他们能在运行前推迟确定模块连接点和数据流。因为这些决定既非硬编码,也不是直接链接,开发人员能根据实际情况或要求的变化改变决定;甚至还能在系统运行时动态地更改决定。
松耦合 PPS 消息传递模型还能简化新软件组件的集成。由于发布者和订阅者不必认识对方,因此增加组件的开发人员只需确定这些新组件的发布内容,以及他们需要其他 PPS客户端发布的数据内容。无需精确调整应用程序接口;系统复杂性不会随组件的增加而加剧。
参考应用程序
作为 QNX 软件系统公司工业自动化程序的一部分,我们在运行 QNX Neutrino RTOS 的系统中设计和创建了 QNX智能家用能源管理系统参考应用程序。这种参考应用程序专门用于解决嵌入式工业应用程序计算资源有限的问题。它集成了大量不同的设备(如传感器、摄像头)和软件组件;使用了采用不同技术创建的尖端触屏式人机界面;支持集成新设备和新组件并能连续多年进行加倍升级。
简化系统架构
在我们的参考应用程序中采用 PPS 消息传递的一个关键优势是,只需两种扩展就能连接人机界面和系统的其余部分:一个用于 PPS,另一个用于 QDB,即 QNX 数据库服务器。假如使用其他消息传递模型,我们就得为系统中通过PPS(利用单独扩展)与每种技术中的组件通信的所有软件组件编写扩展。同样,PPS 消息传递模型允许我们在需要时为系统增加更多组件,而无需编写新扩展或重新访问系统组件之间的通信。
在使用其他消息传递模型的系统中,传感器和组件彼此紧密联系而且会与人机界面密切联系。每个组件都要了解需要与其交换数据的其他组件,在这种系统架构中更改或增加内容势必会困难重重、耗费时间、充满风险。
而使用 PPS 时,组件甚至都不必知道彼此在系统中的存在。例如,增加防盗报警器或新程序(控制从太阳能电池板向电网送电)时,这些新组件只要将其需要共享的数据发布到 PPS 对象中并订阅会为其提供所需数据的对象即可。控制为电网送电的应用程序能读取已使用的 PPS 对象,并向人机界面通报电网负荷和电价信息以获取其所需的数据,进而确定应何时向电网送电。PPS 消息传递架构的另一个重要优势是能简化测试,因为增加新组件无需重新访问其他所有组件之间的消息传递。
结论
PPS 消息传递模型非常适用于必须将不同设备和软件组件集成在复杂人机界面下的嵌入式工业系统。一个采用多种人机界面技术的系统只需应用单独的 PPS 扩展就能确保每种技术与其他系统组件的通信。此外,组件只会根据实现服务的需要发布和订阅 PPS 对象,它们不需要了解对方,因此不费吹灰之力就能扩展或修改系统。实际上,PPS 组件的松耦合架构使更改、升级和扩展任务变得更加轻松,从而减少了风险并提高了系统的长期可靠性。