使用 message buffer 传递数据

使用 message buffer 传递数据

概述

MessageBuffer,即消息缓冲区,是在流式缓冲区的基础上实现的针对离散消息的专用通信组件,其进一步针对“消息”进行设计改进。

StreamBuffer 的基础上,MessageBuffer 对每条数据的长度进行了记录。MessageBuffer每一条消息的写入增加了一个字段用来表示该条消息的长度。读取时需要一次性读出至少一条消息,否则会返回读取失败。

如下所示,在使用 MessageBuffer 时发送数据的一方在调用发送数据的接口时,组件会自动记录该条消息的长度。接收数据的一方接收到该条数据时,可以知道该条数据的长度。而 StreamBuffer 会把这些数据处理成连续的字节流,没有明确的区分它们到底属于什么结构的数据。

在这里插入图片描述
与 StreamBuffer 一样,MessageBuffer 适用于 一个发送者、一个接收者的数据通信场景。在多个发送者、接收者时需要添加互斥保护机制。

主要的 API 如下:

// 使用动态分配的内存创建新的消息缓冲区
MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes ); //消息缓冲区在任何时候都能够保存的总字节数(不是消息)。当消息写入消息缓冲区时,还会写入额外的大小(size_t)字节来存储消息的长度。例如存入一个 8bytes 的消息,则共使用的存储空间为 sizeof(size_t) + 8.

size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer, // 消息缓冲区的句柄。
                           const void *pvTxData, // 要复制到消息缓冲区的消息的指针。
                           size_t xDataLengthBytes, // 消息的长度。即,要从 pvTxData 复制到消息缓冲区的字节数。当消息写入消息缓冲区时,还会写入额外的大小(size_t)字节来存储消息的长度。
                           TickType_t xTicksToWait ); // 无法发送该条消息时,最大等待的时间。若发送成功则唤醒等待消息的任务。

size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,// 消息缓冲区的句柄。
                              void *pvRxData, // 指向要将收到的消息复制到的缓冲区的指针。
                              size_t xBufferLengthBytes, // pvRxData 参数所指向的缓冲区的长度。这将设置可以接收的消息的最大长度。如果 xBufferLengthBytes 太小而无法容纳下一条消息,则该消息将保留在消息缓冲区中,并返回 0。
                              TickType_t xTicksToWait ); // 等待消息的最大延时时间。

需求及功能解析

示例给出了使用 MessageBuffer 发送两种不同的离散消息的场景:

uint8_t ArrayToSend1[] = { 0, 1, 2, 3 }; // 短数据串
uint8_t ArrayToSend2[] = { 4, 5, 6, 7, 8, 9}; // 长数据串

示例解析

使用 MessageBuffer 发送两种不同的离散消息的示例输出如下:

This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, Minimum free heap size: 295348 bytes
TASK1: array is 1
TASK2: receive length is 4
TASK2: The buffer data is as follows:00 01 02 03 
TASK1: array is 2
TASK2: receive length is 6
TASK2: The buffer data is as follows:04 05 06 07 08 09 
TASK1: array is 1
TASK2: receive length is 4
TASK2: The buffer data is as follows:00 01 02 03 
TASK1: array is 2
TASK2: receive length is 6
TASK2: The buffer data is as follows:04 05 06 07 08 09 
TASK1: array is 1
TASK2: receive length is 4
TASK2: The buffer data is as follows:00 01 02 03 

讨论

1)存储身份证号和手机号的场景中,使用 queue、stream buffer、message buffer 时的示意图如下:

在这里插入图片描述

队列因为只能存储固定大小的数据,它需要按照最长的数据“身份证号”分配两块空间来存储身份证号+手机号。并且接收方要接收两次数据才能接收一次完整的身份证号+手机号。

流式缓存区可以存储身份证号和手机号,但它没有记录两者的长度,不容易区分到底哪部分数据属于身份证号、哪部分属于手机号,它不适合处理离散的数据块。

消息缓存区存储身份证号、手机号,并自动地记录它们的长度,最适合处理这种离散的消息。

2)目前讲述的通信组件 queue、StreamBuffer、MessageBuffer都具备一定的缓存能力,但他们都没有提供管理数据溢出的机制,即缓冲区写满之后,再次写入数据如何处理的问题,我们将在下一节介绍一种提供这个溢出管理机制的通信组件-ringbuffer。

总结

1)队列 queue 处理固定大小的消息,通常是一个结构,但它也可以是一个包含指针的基类型。StreamBuffer 流缓冲区将消息作为字节流进行处理。消息将作为一个单元放入队列中,并且没有任何固定大小(只是它应该适合缓冲区的最大值),并且在取出时,可以以任意长度检索获取存入的数据。消息缓冲区保存具有固定大小的离散消息,但每条消息不必具有相同的大小,并且在取出时,消息的形式与存入时完全一致。

2)MessageBuffer 与 StreamBuffer 一样,适用于 一个发送者、一个接收者的数据通信场景。在多个发送者、接收者时需要添加互斥保护机制。

资源链接

1)Learning-FreeRTOS-with-esp32 系列博客介绍
2)对应示例的 code 链接 (点击直达代码仓库)

3)下一篇:使用 Ring Buffer 完成数据传递

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

物联网老王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值