Zephyr zbus - 1 基本概念

Creative Commons
本作品采用知识共享署名

本文说明zbus基本概念,作为使用和分析zbus的基础。

zbus:Zephyr消息总线(Zephyr message bus))是一个轻量级、灵活和可扩展的消息传递机制,用于在不同的设备和应用程序之间进行通信。在3.3.0 release正式出现。它提供了一种简单的方式,使得线程之间可以相互发送和接收消息,从而实现数据共享和协作。zbus提供轻量级和灵活的消息总线,可以使线程之间进行简单的通信。它实现了消息传递和发布/订阅通信范例,允许线程通过共享内存同步或异步地进行通信。zbus的通信是基于通道的,其中线程使用消息进行发布和读取。下图为zephyr官方文档给出的zbus典型应用架构:

外设,传感器,网络和App之间通过zbus上不同的channel按照约定的消息通信。

为了更好的说明和理解zbus,需要先说明zbus定义的一些基本概念。

基本概念

定义

通道(Channel):通道是zbus中的基本单元,用于在不同线程之间传递消息。每个通道都有一个唯一的名称和一个与之相关联的消息类型。
观察者(Observer):观察者订阅特定通道并接收其消息。观察者可以是异步订阅者或同步监听者。
消息(Message):消息是在zbus中传递的数据单元。每个消息都与特定通道相关联,并且必须与该通道关联的消息类型匹配。
消息类型(Message Type):消息类型是用于定义特定通道所使用的消息结构体类型。每个通道只有一个唯一的消息类型。
发布(Publishing):发布是将消息发送到特定通道以供观察者接收的过程。
订阅(Subscription):订阅是指观察者向特定通道注册以接收其发布的所有消息的过程,订阅是异步过程。
监听(Listening):监听是指观察者等待并接收来自特定通道发布的所有消息的过程,监听是同步过程。
验证器(Validator):验证器是用于验证消息是否有效并符合预期格式和内容规则的函数或回调函数。

通道可以编译期静态申请也可以运行期动态申请。观察者可以编译期静态指定也可以运行时动态指定。

运作关系

zbus上各对象的运作关系如下

  1. 观察者订阅或者监听某个通道。
  2. 发布者将消息发布到指定通道上。
  3. 发布前通道会先用验证器检查消息是否合规。
  4. 观察者收到消息。

消息的传递顺序如下

  1. 静态监听者(static listeners):静态监听器是在应用程序启动时注册的观察者。它们会在所有其他观察者之前接收到通知。
  2. 运行时监听者(runtime listeners):运行时监听器是在应用程序运行时动态注册的观察者。它们会在所有静态订阅者之前接收到通知。
  3. 静态订阅者(static subscribers):静态订阅者是在应用程序启动时注册的观察者。它们会在所有运行时订阅者之前接收到通知。
  4. 运行时订阅者(runtime subscribers):运行时订阅者是在应用程序运行时动态注册的观察者。它们会最后接收到通知。

监听者是同步处理消息,会严格按照消息的顺序执行。而订阅者是异步处理消息,处理顺序和订阅者线程的优先级和处理流程相关。

特性

多线程通信:zbus允许不同线程之间通过通道共享内存进行通信,从而实现多线程之间的数据交换。
发布/订阅模型:zbus支持发布/订阅模型,使得多个观察者可以同时接收到同一个消息。
异步和同步通信:zbus支持异步和同步通信,使得开发人员可以根据需要选择最适合其应用程序的通信模式。
灵活的消息类型定义:zbus允许开发人员定义自己的消息类型,并将其与特定通道相关联。消息可以是静态也可以是动态的。
可扩展性:zbus具有高度可扩展性,可以轻松地添加新的观察者、通道和验证器。
易于使用:zbus提供了简单易用的API,使得开发人员可以轻松地使用它来实现多线程通信。

扩展和易用的举例

在官方文档提供了下图说明zbus的应用方式

通道 发布者 订阅者 监听者 作用
START TRIGGER Timer Sensor Thread Blink Callback Timer通知Sensor Thread读取传感器值,并同时通知监听者
SENSOR DATA Sensor Thread Core Thread NA Sensor Thread将传感器的值发送给Core Thread处理
PAYLOAD Core Thread LoRa Thread NA Core Thread处理完传感器后的数据通过提交给LoRa Thread
TRANSMISSION DONE LoRa Thread NA Blink Callback LoRa发送数据完成后通知给监听者

这种实施解决方案的方式使应用程序更加灵活。 例如:我们想将触发器从定时器更改为按钮按下,我只用将按键消息发送到START TRIGGER通道上,这样的更改不会影响系统的其他部分。 同样,我们想将通信接口从 LoRa 更改为蓝牙,则只需要更改LoRa线程。 基于此,zbus在系统架构可以促进各模块之间解耦。
zbus还可以促进系统模块的重用。 具有明确定义行为的模块仅使用 zbus 通道而不使用硬件接口,只要大家都用兼容的消息类型,则可以很容易地在其他解决方案中重用。 新解决方案只需要按照通道的消息类型实现接口即可。

限制

发布和订阅读取在只能在线程上下文中使用,有监听者的通道无法在ISR中进行发布。
对订阅者无消息交付顺序的保证。
吞吐量不够,不适合高速字节流(Benchmark在qemu上显示平均速度约为1.8MB/s)。不过在esp32c3上速度尚可

1
2
3
4
5
⚌*** Booting Zephyr OS build zephyr-v3.3.0 ***
I: Benchmark 1 to 8: Dynamic memory, SYNC transmission and message size 256
I: Bytes sent = 262144, received = 262144
I: Average data rate: 38.86MB/s
I: Duration: 6431.937us

参考

https://docs.zephyrproject.org/3.3.0/services/zbus/index.html