目录

  • 邮箱的概念
  • 运作机制
  • 邮箱的控制块
  • 应用场合
  • 参考

邮箱的概念

邮箱在操作系统中是一种常用的IPC通信方式,邮箱可以在线程与线程之间。中断与线程之间进行消息的传递,此外,邮箱相比于信号量与消息队列来说,其开销更低,效率更高,所以常用来做线程与线程、中断与线程间的通信。邮箱中的每一封邮件只能容纳固定的4字节内容(STM32是32位处理系统,一个指针的大小即为4个字节,所以一封邮件恰好能够容纳一个指针),当需要在线程间传递比较大的消息时,可以把指向一个缓冲区的指针作为邮件发送到邮箱中。

线程能够从邮箱里面读取邮件消息,当邮箱中的邮件是空时,根据用户自定义的阻塞时间决定是否挂起读取线程;当邮箱中有新邮件时,挂起的读取线程被唤醒,邮箱也是一种异步的通信方式。

通过邮箱,线程或中断服务函数可以将一个或多个邮件放入邮箱中。同样,一个或多个线程可以从邮箱中获得邮件消息。当有多个邮件发送到邮箱时,通常应将先进入邮箱的邮件先传给线程,也就是说,线程先得到的是最先进入邮箱的消息,即先进先出原则(FIFO),同时RT-Thread中的邮箱支持优先级,也就是说在所有等待邮件的线程中优先级最高的会先获得邮件。

RT-Thread中使用邮箱实现线程异步通信工作,具有如下特性:

  • 邮件支持先进先出方式排队与优先级排队方式,支持异步读写工作方式。
  • 发送与接收邮件均支持超时机制
  • 一个线程能够从任意一个消息队列接收和发送邮件。
  • 多个线程能够向同一个邮箱发送邮件和从中接收邮件。
  • 邮箱中的每一封邮件只能容纳固定的4字节内容(可以存放地址)。
  • 当队列使用结束后,需要通过删除邮箱以释放内存。

邮箱与消息队列很相似,消息队列中消息的长度是可以由用户配置的,但邮箱中邮件的大小却只能是固定容纳4字节的内容,所以,使用邮箱的开销是很小的,因为传递的只能是4字节以内的内容,那么其效率会更高。

运作机制

创建邮箱对象时会先创建一个邮箱对象控制块,然后给邮箱分配一块内存空间用来存放邮件,这块内存的大小等于邮件大小(4字节)与邮箱容量的乘积,接着初始化接收邮件和发送邮件在邮箱中的偏移量,接着再初始化消息队列,此时消息队列为空。

线程或者中断服务程序都可以给邮箱发送邮件,非阻塞方式的邮件发送过程能够安全的应用于中断服务中,中断服务函数、定时器向线程发送消息的有效手段,而阻塞方式的邮件发送只能应用于线程中。当发送邮件时,当且仅当邮箱还没满邮件的时候才能进行发送,如果邮箱已满,可以根据用户设定的等待时间进行等待,当邮箱中的邮件被收取而空出空间来时,等待挂起的发送线程将被唤醒继续发送的过程,当等待时间到了还未完成发送邮件,或者未设置等待时间,此时发送邮件失败,发送邮件的线程或者中断程序会收到一个错误码(-RT_EFULL)。线程发送邮件可以带阻塞,但在中断中不能采用任何带阻塞的方式发送邮件。

邮箱的控制块

struct rt_mailbox
{struct rt_ipc_object parent;rt_uint32_t* msg_pool;                /* 邮箱缓冲区的开始地址 */rt_uint16_t size;                     /* 邮箱缓冲区的大小     */rt_uint16_t entry;                    /* 邮箱中邮件的数目     */rt_uint16_t in_offset, out_offset;    /* 邮箱缓冲的进出指针   */rt_list_t suspend_sender_thread;      /* 发送线程的挂起等待队列 */
};
typedef struct rt_mailbox* rt_mailbox_t;

应用场合

邮箱是一种简单的线程间消息传递方式,特点是开销比较低,效率较高。在 RT-Thread 操作系统的实现中能够一次传递一个 4 字节大小的邮件,并且邮箱具备一定的存储功能,能够缓存一定数量的邮件数 (邮件数由创建、初始化邮箱时指定的容量决定)。邮箱中一封邮件的最大长度是 4 字节,所以邮箱能够用于不超过 4 字节的消息传递。由于在 32 系统上 4 字节的内容恰好可以放置一个指针,因此当需要在线程间传递比较大的消息时,可以把指向一个缓冲区的指针作为邮件发送到邮箱中,即邮箱也可以传递指针,例如:

struct msg
{rt_uint8_t *data_ptr;rt_uint32_t data_size;
};

对于这样一个消息结构体,其中包含了指向数据的指针 data_ptr 和数据块长度的变量 data_size。当一个线程需要把这个消息发送给另外一个线程时,可以采用如下的操作:

struct msg* msg_ptr;msg_ptr = (struct msg*)rt_malloc(sizeof(struct msg));
msg_ptr->data_ptr = ...; /* 指向相应的数据块地址 */
msg_ptr->data_size = len; /* 数据块的长度 */
/* 发送这个消息指针给 mb 邮箱 */
rt_mb_send(mb, (rt_uint32_t)msg_ptr);

而在接收线程中,因为收取过来的是指针,而 msg_ptr 是一个新分配出来的内存块,所以在接收线程处理完毕后,需要释放相应的内存块

struct msg* msg_ptr;
if (rt_mb_recv(mb, (rt_uint32_t*)&msg_ptr) == RT_EOK)
{/* 在接收线程处理完毕后,需要释放相应的内存块 */rt_free(msg_ptr);
}

参考

本节笔记参考于:野火-《RT-Thread内核实现与应用开发实战》
韦东山 《RT-Thread完全开发手册之内核机制》
以及RT-Thread官网:邮箱

RT-Thread学习笔记(9):邮箱相关推荐

  1. (uC/OS-II学习笔记) 消息邮箱消息队列

    原文出处: http://www.cnblogs.com/hebaichuanyeah 与信号量一样,消息邮箱与消息列队都是一种事件块. 消息邮箱可以在任务间实现信息传递. 比如,在任务1中发送一条消 ...

  2. RT-Thread 入门学习笔记 - 熟悉邮箱rt_mailbox的使用

    简介 邮箱是用来传输邮件的,如果没人取件,会暂存下来. RT-Thread的邮箱,传递的是一个4字节(32位)值,可以传值,可以传指针(32位MCU,指针为32位). 邮箱使用比消息队列更精简,简单的 ...

  3. 源码学习笔记-网易邮箱登陆页面

    不知道为什么出来效果不一样?上面是菜鸟编辑器,下面是记事本,可能缺少图片的原因 <html>   <head>     <title>111</title&g ...

  4. [Systemverilog学习笔记] Thread Communication-Event、Semaphore、mailbox

    [Systemverilog学习笔记] Thread Communication-Event.Semaphore.mailbox 学习目标: 通过下文了解Event.Semaphore.mailbox ...

  5. 第98讲:使用SBT开发时动手解决rt.jar中CharSequence is broken等问题学习笔记

    第98讲:使用SBT开发时动手解决rt.jar中CharSequence is broken等问题学习笔记 几乎所有从IDEA官网上下载安装在win上,采用默认方式自动运行的都 会遇到这个问题. er ...

  6. THREAD APC 《寒江独钓》内核学习笔记(4)

    继续学习windows 中和线程有关系的数据结构: ETHREAD.KTHREAD.TEB 1. 相关阅读材料 <windows 内核原理与实现> --- 潘爱民 2. 数据结构分析 我们 ...

  7. GEE学习笔记一账号注册(只需要用谷歌邮箱就能注册成功)

    小白辰某的GEE学习笔记一 gee账号注册的雷,我先踩为敬 为了申请成功我真的是看遍了知乎和csdn上所有的文章,以下随便写写我踩的雷点.本人写的小文章,统统都是纯干货,简单明了,新手必备(不吹不黑你 ...

  8. RT-Thread 邮箱(学习笔记)

    本文参考自[野火EmbedFire]<RT-Thread内核实现与应用开发实战--基于STM32>,仅作为个人学习笔记.更详细的内容和步骤请查看原文(可到野火资料下载中心下载) 文章目录 ...

  9. Spring Boot学习笔记-基础(2)

    Spring Boot学习笔记-基础(2) Spring Boot 优点: – 快速创建独立运行的Spring项目以及与主流框架集成 – 使用嵌入式的Servlet容器,应用无需打成WAR包 – st ...

  10. Spring Boot 2 学习笔记(2 / 2)

    Spring Boot 2 学习笔记(1 / 2) - - - 45.web实验-抽取公共页面 46.web实验-遍历数据与页面bug修改 47.视图解析-[源码分析]-视图解析器与视图 48.拦截器 ...

最新文章

  1. 离ExtJS 4.1 beta发布只剩26个bug了
  2. require js define 函数
  3. 机房收费系统-- MDI子窗体显示技巧(续vb.net版)
  4. glutSolidSphere 用例
  5. MTK-TP(电阻屏校准程序ts_lib移植)
  6. Cachefiled
  7. 概述嵌入式设备驱动,教你怎么“玩”转嵌入式开发
  8. 写给90后快30岁的我们
  9. java 场景处理,最适合使用RxJava处理的四种场景
  10. 背景图怎么置于底层_Ps素材教程含有刻度的背景图
  11. Python画等高线以及标注
  12. 2.精通前端系列技术之JS模块化开发-深入学习seaJs(四)
  13. [Prescan] Prescan与Simulink联合
  14. python 概率分布_Python中的联合概率分布
  15. C语言-Switch 语句
  16. python爬虫项目(对博思平台社区话题信息进行爬取并保存)
  17. python 弱引用
  18. HTML+CSS+JS网页设计与制作期末大作业:网站——宏源山庄
  19. 利用七牛存储7天远程自动备份LINUX服务器
  20. 后端开发如何快速转前端开发

热门文章

  1. html如何把图片在背景图一半,img只显示图片一部分 或 css设置背景图片只显示图片指定区域...
  2. poky linux初探 -- 添加自己的内核食谱
  3. 银河麒麟连不上网怎么办
  4. “外卖式”售后服务体验来袭 沃丰科技ServiceGo让售后服务更智能
  5. 将一个Excel中的数据导入DataGrid中
  6. 报告|中国智能音箱已入局全球市场,双重商业模式迅速扩张
  7. fairyGUI的学习记录1
  8. 【Autopsy数字取证篇】Autopsy数字取证软件的下载安装与优化配置
  9. Log4j2 重大漏洞与解决方案
  10. GUI窗口不显示图片背景图片,和布局后不显示组件,的根本原因和解决办法