源码已经上传至我的 [Gitee](https://gitee.com/ascloudwalker),可用如下代码下载:
git clone https://gitee.com/ascloudwalker/c-publish--subscribe.git
- 前言
最近接触到一些工程上的代码,使用全局变量或者函数指针的方式进行数据传递,在某些时候不是很方便:
- 通过函数一层一层传递数据很麻烦;
- 修改全局变量不可控;
此时,我想起了PX4的uORB(Micro Object Request Broker,微对象请求代理器)。
- 原理
uORB本质上是一种发布订阅模式,什么是发布订阅模式?发布订阅模式:假设存在老师T(teacher),黑板B(blackboard),同学S(student).老师T每隔一个时间t1就去黑板B上发布一则通知,学生S每隔一段时间就去看(订阅)黑板上以下老师发布了什么消息。当然,这是最简单的模式,实际应用中实现还有很多附加功能,比如说:实际实现中,学生并不会先去看黑板上的内容,他可能通过某种机制先检查黑板上的内容是否更新,如果没更新就没有必要去看,如果更新了就去看看写了什么。又比如多个老师都可以在黑板上发布消息,也可以有多个同学去查看黑板发布了什么,当然也会有多块黑板。
以上是一种通俗的说法,通俗的优点是好理解,缺点是显得Low。如果想要显得更加专业,请参考以下文章。
- 一天精通无人机第 19 讲 中级篇系列:uORB原理与使用
- RabbitMQ译文 — 发布/订阅(Publish/Subscribe)
- The Publisher-Subscriber Pattern
再好的想法,只有实现了才能发挥作用,我开始查找现成的源码。
- 首先,PX4的uORB、ROS等成熟的代码中都有该功能,优点是代码完善、功能齐全、结构完备;缺点是繁杂,不适合初学者理解,就算是看明白了也记不住;
- 其次,网上一些单独的所谓发布订阅模式实现,与我所想的有些差别。
我决定,将uORB中最基本的架构抽离出来,使用Visual Studio C++实现。首先列出参考资源以示尊敬:
- 实现
干饭人干饭魂,干完代码干工程,我想实现最简单的功能,构建四个线程:
1. 主线程:1000ms/1HZ,打印主线程运行次数;
2. 线程:50ms/20HZ,发布一次更新数据;
3. 线程1:100ms/10HZ,订阅数据并打印;
4. 线程2:100ms/10HZ,订阅数据并打印
实现方法,当前的PX4版本,uORB的封装更好,代码结构更加简洁,但是不便于提取结构,本文主要参考了zarathustr /uORB提取出来的一个可移植版本,并在其基础上构建了Visual C++工程:
> step1: 构建黑板
// uORB.h
/// 这相当于定义黑板的基本结构
struct Data {
void *data = nullptr;
bool published = false;
};
extern Data *topic_data[1];
// pubsub.cpp
/// 实例化黑板,需要发布多少个主题(topic),就需要实例化多少黑板
const int total_uorb_num = 1;
Data *topic_data[total_uorb_num];
// pubsub.cpp
/// 对象请求代理器初始化,主要是因为结构体指针必须初始化,可以通过断点运行查看该步骤的作用
void orbInit(void)
{
for (int i = 0; i < total_uorb_num; ++i)
{
<