邮箱工作机制

RT-Thread 操作系统的邮箱用于线程间通信,特点是开销比较低,效率较高。邮箱中的每一封邮件只能容纳固定的4字节内容(针对32位处理器系统,指针大小即为4个字节,所以一封邮件恰好能够容纳一个指针)。

线程或ISP(中断服务程序)把一封4字节长度的邮件发送到邮箱中,而其他需要的线程可以从邮箱中接收这些邮件并进行处理。

邮箱控制块

struct rt_mailbox
{struct rt_ipc_object parent;                        /**< inherit from ipc_object */rt_ubase_t          *msg_pool;                      /**< start address of message buffer */rt_uint16_t          size;                          /**< size of message pool */rt_uint16_t          entry;                         /**< index of messages in msg_pool */rt_uint16_t          in_offset;                     /**< input offset of the message buffer */rt_uint16_t          out_offset;                    /**< output offset of the message buffer */rt_list_t            suspend_sender_thread;         /**< sender thread suspended on this mailbox */
};
typedef struct rt_mailbox *rt_mailbox_t;

rt_mailbox_t 是一个rt_mailbox 型的指针

成员 说明
parent 从系统IPC 对象继承
msg_pool 邮箱中消息的缓存区起始地址
size 邮箱大小
entry 邮箱中邮件个数的指示
in_offset 邮箱缓存区的进偏移量
out_offset 邮箱缓存区的出偏移量
suspend_sender_thread 挂起在邮箱上的发送线程(当邮箱已满,又想发送邮件的线程)

定义静态邮箱

(定义一个结构体)

struct rt_mailbox static_mb

定义动态邮箱

(定义一个结构体指针)

rt_mailbox_t dynamic_mb

邮箱的操作

初始化与脱离

邮箱的初始化与脱离是针对静态邮箱的。

rt_err_t rt_mb_init(rt_mailbox_t mb,const char  *name,void        *msgpool,rt_size_t    size,rt_uint8_t   flag);rt_err_t rt_mb_detach(rt_mailbox_t mb);

rt_mb_init

参数 说明
mb 邮箱控制块指针
name 邮箱名称
msgpool 邮箱缓存区地址
size 邮箱大小
flag 等候线程的排队方式(RT_IPC_FLAG_FIFO、RT_IPC_FLAG_PRIO)

调用邮箱初始化或脱离API 就会分别将邮箱添加进系统管理器中或将邮箱从系统管理器中脱离。

创建与删除

邮箱的创建与删除是针对动态邮箱的。

rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag);rt_err_t rt_mb_delete(rt_mailbox_t mb);

rt_mb_create

可见该API 相比静态邮箱的初始化API 缺少了mb、msgpool 参数,因为动态邮箱是根据邮箱大小在系统中申请一段动态内存,创建成功返回一个邮箱指针

参数 说明
name 邮箱名称
size 邮箱大小
flag 等候线程的排队方式(RT_IPC_FLAG_FIFO、RT_IPC_FLAG_PRIO)

调用邮箱创建与删除API 就会分别创建邮箱进系统管理器中或将邮箱从系统管理器中移除。

发送邮件

rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value);rt_err_t rt_mb_send_wait(rt_mailbox_t mb,rt_ubase_t  value,rt_int32_t   timeout);

rt_mb_send

该函数本质上就是参数timeout 为零的rt_mb_send_wait 函数

参数 说明
mb 邮箱指针
value 要发送的邮件内容

value 可以直接是要发送的邮件内容,也可以是邮件地址。

若邮箱已满,调用此函数将返回错误标志-RT_EFULL

rt_mb_send_wait

参数 说明
mb 邮箱指针
value 邮件内容
timeout 超时时间

value 可以直接是要发送的邮件内容,也可以是邮件地址。

若邮箱已满,则会根据timeout 进行相应时间等待。


rt_mb_send 函数(即timeout = 0的 rt_mb_send_wait 函数)可以在线程和中断中调用,当timeout 不为零时,rt_mb_send_wait 函数只能在线程中调用。

接收邮件

rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout);
参数 说明
mb 邮箱地址
value 存储邮件的内存地址(注意:此处需要传入指针的取地址,见例程)
timeout 等待超时时间(当邮箱为空时)

邮箱使用示例

#define THREAD_PRIORITY      10
#define THREAD_TIMESLICE     5/* 邮箱控制块 */
static struct rt_mailbox mb;
/* 用于放邮件的内存池 */
static char mb_pool[128];static char mb_str1[] = "I'm a mail!";
static char mb_str2[] = "this is another mail!";
static char mb_str3[] = "over";ALIGN(RT_ALIGN_SIZE)
static char thread1_stack[1024];
static struct rt_thread thread1;/* 线程1入口 */
static void thread1_entry(void *parameter)
{char *str;while (1){rt_kprintf("thread1: try to recv a mail\n");/* 从邮箱中收取邮件 */if (rt_mb_recv(&mb, (rt_uint32_t *)&str, RT_WAITING_FOREVER) == RT_EOK){rt_kprintf("thread1: get a mail from mailbox, the content:%s\n", str);if (str == mb_str3)break;/* 延时100ms */rt_thread_mdelay(100);}}/* 执行邮箱对象脱离 */rt_mb_detach(&mb);
}ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;/* 线程2入口 */
static void thread2_entry(void *parameter)
{rt_uint8_t count;count = 0;while (count < 10){count ++;if (count & 0x1){/* 发送mb_str1地址到邮箱中 */rt_mb_send(&mb, (rt_uint32_t)&mb_str1);}else{/* 发送mb_str2地址到邮箱中 */rt_mb_send(&mb, (rt_uint32_t)&mb_str2);}/* 延时200ms */rt_thread_mdelay(200);}/* 发送邮件告诉线程1,线程2已经运行结束 */rt_mb_send(&mb, (rt_uint32_t)&mb_str3);
}int mailbox_sample(void)
{rt_err_t result;/* 初始化一个mailbox */result = rt_mb_init(&mb,"mbt",                      /* 名称是mbt */&mb_pool[0],                /* 邮箱用到的内存池是mb_pool */sizeof(mb_pool) / 4,        /* 邮箱中的邮件数目,因为一封邮件占4字节 */RT_IPC_FLAG_FIFO);          /* 采用FIFO方式进行线程等待 */if (result != RT_EOK){rt_kprintf("init mailbox failed.\n");return -1;}rt_thread_init(&thread1,"thread1",thread1_entry,RT_NULL,&thread1_stack[0],sizeof(thread1_stack),THREAD_PRIORITY, THREAD_TIMESLICE);rt_thread_startup(&thread1);rt_thread_init(&thread2,"thread2",thread2_entry,RT_NULL,&thread2_stack[0],sizeof(thread2_stack),THREAD_PRIORITY, THREAD_TIMESLICE);rt_thread_startup(&thread2);return 0;
}/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(mailbox_sample, mailbox sample);

RT-Thread 内核学习 (十三)邮箱的使用相关推荐

  1. STM32 + RT Thread OS 学习笔记[五]

    1.  触摸屏驱动 触摸屏驱动的原理非常简单,从硬件得到坐标数据,数据加工(适配屏幕分辨率,偏移量调整),最后调用rtgui_server_post_event()函数向GUI服务端发送坐标信息. 奋 ...

  2. Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32

    1.前言     [2014年4月重写该博文]     经过若干时间的努力终于搞定了STM32+LwIP和yeelink平台的数据互通,在学习的过程中大部分时间花在以太网协议栈学习上,但是在RT Th ...

  3. 《寒江独钓》内核学习笔记

    <寒江独钓>内核学习笔记(1)-- IRP - .Little Hann 时间 2013-11-30 15:40:00  博客园_.Little Hann原文  http://www.cn ...

  4. 关于RT thread系统节拍时钟的配置

    关于RT thread系统节拍时钟的配置                  -----本文基于rt-thread-3.1.3版本编写 首先,使用RTthread OS时,要配置(或者明白)它的系统节拍 ...

  5. RT Thread之 Uart2 操作

    官网连接:https://docs.rt-thread.org/#/rt-thread-version/rt-thread-standard/programming-manual/device/uar ...

  6. 基于rt thread smart构建EtherCAT主站

    我把源码开源到到了gitee,https://gitee.com/rathon/rt-thread-smart-soem 有兴趣的去可以下载下来跑一下 软件工程推荐用vscode 打开.rt thre ...

  7. 使用RT Thread设备框架封装一个I2C设备——DS3231

    使用RT Thread设备框架封装一个I2C设备--DS3231 前言 ENV配置 I2C测试 将ds3231封装成一个字符设备 结语 前言 学习rt thread的I2C的时候,恰巧手上的板子留了d ...

  8. 基于GD32F103C8T6添加RT Thread nano设备框架并添加串口设备(以控制台console( uart0 )为例)

    最近没事琢磨了一下使用设备框架的问题.因为将串口注册到设备框架可以应用十分丰富的软件包. 于是就整理了一下手上的工程,重新将工程梳理了一遍. 像这样是十分清爽了,其中RTOS是操作系统源代码 并且学习 ...

  9. linux 内核学习2-使用笨叔叔定制的内核

    linux 内核学习2-使用笨叔叔定制的内核 1. 目的 编译一个ARM版本的内核镜像,谁让我是做Android的呢!并且在QEMU上运行. 2. 准备工作 2.1 开发环境 ubuntu 18.4虚 ...

  10. Linux内核学习四库全书

    关于内核学习我建议不要上来就读内核而是先了解内核的构成和特性,然后通过思考发现疑问这时再去读内核源码.即先了解概貌在读局部细节.而且内核分成好多部分,不要只是按照顺序去读,应该针对某一部分比如内存管理 ...

最新文章

  1. 有勇气的牛排---linux
  2. 。net面试题(2)
  3. 获得SAP CRM report的元数据get report detail(Metadata) via url
  4. zeppelin的安装与使用
  5. Blogger建立Blog部落格​​ - Blog透视镜
  6. jQuery实现字体变大和缩小
  7. 【汇编优化】之arm32汇编优化
  8. 树莓派3b接收USB串口数据并解析处理
  9. tomcat并发数设置
  10. [源码]C# to SQL 的翻译器.net 1.1版
  11. ListView控件数据操作——通过代码在窗体上添加控件
  12. 大漠插件最新版dm7.2135
  13. Rocksdb参数总结
  14. Android 一键加速原理
  15. 个人小项目原型图设计(主页)
  16. 为什么说人间值得,因为有这么多美好让我们留恋。金秋十月初九于指南山村 。...
  17. java打印表情包_表情包生成器
  18. win电脑主板设置的Bios密码清除方法
  19. 天宝AMD 300U物理机安装黑群晖处理内存不足的问题
  20. 计算机游戏动漫制作自我鉴定,动画制作专业毕业生的自我鉴定

热门文章

  1. android怎么实现广告页,如何:在Android应用中加入广告方法步骤!
  2. 适配iPhoneX全系详解,更新Xcode10爬坑
  3. php sql漏洞修复,PHPNet = 1.8 (ler.php) SQL注射及修复漏洞预警 -电脑资料
  4. 怎么将pdf转换成jpg格式最简单
  5. matlab归一化相关系数,归一化相关系数
  6. 榆林学院计算机院徐晓林,我校与达内时代科技集团签署计算机科学与技术专业合作共建协议...
  7. 奢华酒店品牌施柏阁今年将进驻中国大陆;丹纳赫诊断平台中国研发制造基地在苏州动工 | 美通企业日报...
  8. js:写入/获取/清除缓存
  9. html封套成exe,刺激封套与植入工具的制作方法
  10. 如何关闭ThinkPad电脑的触摸板