浅析 FreeRTOS 的队列传输数据原理及方式

发布时间:2026/10/4 13:56:43
浅析 FreeRTOS 的队列传输数据原理及方式 底层实现队列传输数据的底层实现是通过memcpy函数实现的内存拷贝。队列创建函数动态QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize )其中uxQueueLength是这个队列最大能容纳的元素数量uxItemSize是每个元素的大小。队列发送数据函数尾插xQueueSend(QueueHandle_t xQueue,const void *const pvItemToQueue, TickType_t xTicksToWait )其中xQueue是所使用的队列的句柄pvItemToQueue是所要传输的数据的起始地址xTicksToWait则是允许阻塞的最长时间。xQueueSend的底层实现便是从pvItemToQueue所指向的地址开始使用memcpy函数拷贝uxItemSize长度字节的内存到xQueue的队列环形缓冲区的pcWriteTo所指向的内存实现数据的拷贝。了解了上述内容再来看接下来的三种数据拷贝方式。三种拷贝三种拷贝方式分别是深拷贝、浅拷贝、零拷贝。由其名称也能看出三种拷贝真正所拷贝的数据的大小越来越小直到零拷贝完全未对任何数据进行拷贝。传值Queue by Value可近似理解为深拷贝深拷贝即将所有要拷贝的数据原原本本的拷贝到目标内存中。这种拷贝方式最耗费内存和时间但是对要拷贝的变量的存储方式没什么要求也就是可以对局部变量进行拷贝。在使用队列发送数据时如果使用的的队列句柄所指向的队列在创建时的uxItemSize是sizeof(data_t)也就是数据块本身的大小那此时所使用的方式就是深拷贝。传引用Queue by Reference可近似理解为浅拷贝浅拷贝即只将要拷贝的数据的地址拷贝到目标内存只拷贝一个指针变量的大小。这种拷贝方式耗费时间近乎于 0 。但是由于数据接收方想要访问这块数据前提是传来的指针最终指向的数据必须能在原函数结束之后继续存在也就是不能存储于函数的栈帧内不能是局部变量。这就要求这个指针要指向通过动态分配的内存或者是一个全局变量。在使用队列发送数据时如果使用的的队列句柄所指向的队列在创建时的uxItemSize是sizeof(void *)也就是指针的大小并且传入的pvItemToQueue是指向数据的指针的地址那此时所使用的方式就是浅拷贝。基于共享内存的零拷贝Zero Copy零拷贝顾名思义就是不对任何内存进行拷贝。零拷贝是利用共享内存进行实现的所以此时数据的发送、接收方实际上需要的仅是共享内存写入 / 读取完毕的通知。这种拷贝方式完全不耗费任何拷贝时间只需要考虑到通知对方的时间。由于完全不需要拷贝这种方式其实可以脱离队列进行实现需要的只是一块共享内存以及消息通知机制。这个消息通知机制可以是二进制信号量、互斥量、事件组、任务通知效率最高等等。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询