Concept Zbus实现了一种线程间多对多的消息通信机制。
有三种类型的观察者:
Listener,event dispatcher每次发布或通知通道时,都会执行Listener的回调函数。是同步的。 Subscriber,内部依赖于消息队列,event dispatcher每次发布或通知通道时,都会在其中放置更改的channel的引用。注意,这种观察者本身并不接收消息。收到通知后应主动从通道中读取消息。Subscriber线程中需要主动从channel中读出当前的message。是异步的。 Message subscribers,event dispatcher每次发布或通知通道时,都会copy message到buf中再挂入Message subscribers的message fifo。Message subscribers线程中只需要从message fifo中取出message。是异步的。 For example,在下图中,Timer是Channel Trigger的Publisher,Sensor Thread是Subscriber,Blink是Listener。
当timer发布message后,会执行Blink的回调函数来闪烁,Sensor thread可以获取sensor数据。
Sensor thread处理完数据后,又是Sensor data channel的publisher,发布message后,core thread接收到message,来处理sensor data。
Core thread处理完后,通知LoRa thread,在最后一个channel处理完成后,再次调用Blink的回调函数来闪烁。
可以打开或关闭某个订阅者,某个订阅者也可以选择打开或关闭某个channel。
Virtual Distributed Event Dispatcher 假设一个场景,有一个channelA。T1为publisher,S1为Subscriber,L1,L2为Listener,MS1,MS2为Message Subscriber。
The VDED execution总是发生在publisher’s context, 基本流程为:
给channel上锁 channel通过直接拷贝(memcpy)把new message拷贝过去。 VDED执行listener的回调函数,把message拷贝给message subscriber,把channel reference加入到subscriber的notification message queue。Listener可以通过zbus_chan_const_msg()直接获取message的reference。 给channel解锁 如下图演示了执行流程,假设线程优先级为T1>MS1>MS2>S1:
可以看到Listener只直接引用channel里的message而不用拷贝,而Publisher会把message拷贝到Message subscriber。Subscriber则是当调度到的时候自己去拷贝message。
如果线程优先级为T1<MS1<MS2<S1:
注意此时的执行顺序,在f时,T1发布message,会立刻调度到MS1, 在g时,会立刻调度到MS2。
HLP priority boost Zbus实现了自动提高publisher线程优先级的操作,选项为CONFIG_ZBUS_PRIORITY_BOOST,是默认自动打开的。这样能publisher线程不会像上面一样被打断,可以提高执行效率。
为了使用该特性,需要将observer attach到一个线程:
ZBUS_SUBSCRIBER_DEFINE(s1, 4); void s1_thread(void *ptr1, void *ptr2, void *ptr3) { const struct zbus_channel *chan; zbus_obs_attach_to_thread(&s1); // 将s1 attach到线程 while (1) { zbus_sub_wait(&s1, &chan, K_FOREVER); /* Subscriber implementation */ } } K_THREAD_DEFINE(s1_id, CONFIG_MAIN_STACK_SIZE, s1_thread, NULL, NULL, NULL, 2, 0, 0); Limitation 考虑到Zbus的benchmark,不适用于传输高速流数据。...