Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
内核学习营
个人分享心得(七)——线程间通信(邮箱)
发布于 2019-04-02 15:55:11 浏览:3031
订阅该版
[tocm] * 本帖最后由 家定不举棋 于 2019-4-11 00:10 编辑 * # 邮箱 邮箱 `mailbox`:一种线程间通信的方法,但是每一封邮件只有4个字节的容量。其结构体如下所示: ``` 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; rt_uint16_t out_offset; rt_list_t suspend_sender_thread; }; ``` 从上述结构体中可以看出邮箱也是 `IPC` 的一种内核对象;`size` 是邮箱消息池的容量,但是 `size` 并不是邮箱的真正大小,他的真正含义是邮箱中所能容纳的邮件数量,由动态创建邮箱 `rt_mb_create` 中的下面代码中可以看出真正的邮箱大小由 `msg_pool` 决定。 ``` mb->msg_pool = RT_KERNEL_MALLOC(mb->size * sizeof(rt_uint32_t)); ``` 但是 `msg_pool` 在结构体中表明的是邮箱消息缓存区的起始地址;`entry` 的值是消息池中的索引,即邮箱中当前的邮件数量;`in_offset` 和 `out_offset` 分别是消息缓冲区的输入偏移量和输出偏移量,每当成功发送一封邮件,`in_offset` 便加1,如果成功接收一封邮件,`out_offset` 便加1,他们与 `entry` 最本质的区别便是只增不减,当他们的大小与 `size` 相等时,则将他们置为0。那么以此可以知道 `in_offset` 和 `out_offset` 的作用便是对发送或者接收的邮件进行定位,而这恰恰说明邮箱的本质是循环队列,因为其只允许在队尾进行发送,而在队首进行接收。`suspend_sender_thread` 则是挂起的发送线程链表,当邮箱为满时,线程若继续发送邮件则会挂起发送线程。(若当邮箱为空时,线程继续接收邮件也会被挂起,挂起的接收线程会挂接在 `parent.suspend_thread` 之中)/ 首先对邮箱进行初始化,初始化分为静态初始化 `rt_mb_init` 和 `rt_mb_create`。对于静态初始化的时候,需要注意 `size` 的大小,必须满足 `size * 4 <= sizeof(mb_pool)`。 因为当设定的存储容量大小比邮箱真实容量大时,当接收的邮件数量超邮箱真实容量后,邮箱会继续接收,其邮件会存放在邮箱容量后面的地址,这个操作比较危险,但是不一定会百分百失败。以下代码可以作为参考实验: ``` #include
static struct rt_mailbox mb; static char mb_pool[10]; static char mb_str1[] = "abcdefghijklmnopqrstuvwxyz"; int test_sample(void) { rt_err_t result; rt_uint8_t count = 0; rt_err_t mail_mask = RT_EOK; char *str; result = rt_mb_init(&mb, "test mb", mb_pool, 26, RT_IPC_FLAG_FIFO); if (result != RT_EOK) { rt_kprintf("init mailbox failed.
"); return -1; } rt_kprintf("start send.
"); rt_kprintf("mb.size = %d.
",mb.size); do { mail_mask = rt_mb_send(&mb, (rt_uint32_t)mb_str1[count]); rt_kprintf("mb.msg_pool[%d] = %c.
",count, mb.msg_pool[count]); count ++; } while (mail_mask == RT_EOK); rt_kprintf("count = %d.
", count); rt_kprintf("mail_mask = %d.
", mail_mask); rt_kprintf("mb.entry = %d.
",mb.entry); rt_kprintf("mb.in_offset = %d.
",mb.in_offset); rt_kprintf("mb.out_offset = %d.
",mb.out_offset); count = 0; do { mail_mask = rt_mb_recv(&mb, (rt_uint32_t *)&str, 0); rt_kprintf("the content:%c
", str); count ++; } while (mail_mask == RT_EOK); rt_kprintf("count = %d.
", count); rt_kprintf("mail_mask = %d.
", mail_mask); rt_kprintf("mb.entry = %d.
",mb.entry); rt_kprintf("mb.in_offset = %d.
",mb.in_offset); rt_kprintf("mb.out_offset = %d.
",mb.out_offset); count = 0; return 0; } MSH_CMD_EXPORT(test_sample, test sample); ``` 个人在 `rtthread_simulator` 中新建 `test_sample.c` 文件,对此程序进行运行后输出结果如下: ``` \ | / - RT - Thread Operating System / | \ 3.1.0 build Apr 1 2019 2006 - 2018 Copyright by rt-thread team msh >test_sample start send. mb.size = 26. mb.msg_pool[0] = a. mb.msg_pool[1] = b. mb.msg_pool[2] = c. mb.msg_pool[3] = d. mb.msg_pool[4] = e. mb.msg_pool[5] = f. mb.msg_pool[6] = g. mb.msg_pool[7] = h. mb.msg_pool[8] = i. mb.msg_pool[9] = j. mb.msg_pool[10] = k. mb.msg_pool[11] = l. mb.msg_pool[12] = m. mb.msg_pool[13] = n. mb.msg_pool[14] = o. mb.msg_pool[15] = p. mb.msg_pool[16] = q. mb.msg_pool[17] = r. mb.msg_pool[18] = s. mb.msg_pool[19] = t. mb.msg_pool[20] = u. mb.msg_pool[21] = v. mb.msg_pool[22] = w. mb.msg_pool[23] = x. mb.msg_pool[24] = y. mb.msg_pool[25] = z. mb.msg_pool[26] = . count = 27. mail_mask = -3. mb.entry = 26. mb.in_offset = 0. mb.out_offset = 0. the content:a the content:b the content:c the content:d the content:e the content:f the content:g the content:h the content:i the content:j the content:k the content:l the content:m the content:n the content:o the content:p the content:q the content:r the content:s the content:t the content:u the content:v the content:w the content:x the content:y the content:z the content:z count = 27. mail_mask = -2. mb.entry = 0. mb.in_offset = 0. mb.out_offset = 0. msh > ``` 对于动态创建邮箱则无需考虑这么多,因为动态创建邮箱后确定了 `size` 后,将会进行动态内存分配空间,`msg_pool` 的值在动态分配内存空间后确定。 同样,线程和中断都可以对邮箱进行发送邮件,但是对于中断而言在接收邮件时有特殊情况,若中断触发后没有接收到邮件,那么就会产生错误。若接收等待时间为0,则正常运行,但是接收到的字符为 `RT_NULL`;如果在接收时间内未收到邮件,那么会产生如下错误: ``` msh >Function[rt_mb_recv] shall not be used in ISR (0) assertion failed at function:rt_mb_recv, line number:1645 ``` 同理当邮箱为满时,中断若继续向邮箱发送邮件则也会产生类似错误。
查看更多
4
个回答
默认排序
按发布时间排序
flyboy
2019-04-03
Do my self();
暖贴
DaZhou
2019-04-03
这家伙很懒,什么也没写!
Good Job!
我夏了夏天
认证专家
2019-04-03
Life isn't about finding yourself, life is about creating yourself.
有点厉害 :lol
hzh431213
2020-03-18
这家伙很懒,什么也没写!
``` (rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox) assertion failed at function:rt_mb_recv, line number:1598 [33m[W/UART] Warning: There is no enough buffer for saving data, please increase the RT_SERIAL_RB_BUFSZ option.[0m ``` 这个断言是哪个内存?
撰写答案
登录
注册新账号
关注者
0
被浏览
3k
关于作者
家定不举棋
这家伙很懒,什么也没写!
提问
10
回答
6
被采纳
0
关注TA
发私信
相关问题
1
【内核学习】rtthread内核移植记录-STM32F103ZET6-HAL库
2
《内核学习营》+水一方+自用STM32F103VC 板RT-Thread内核移植分享
3
《内核学习营》+水一方+项目中创建标准的 RT-Thread工程
4
内核学习营+坦然+探索者stm32f407板子RT-thread循环点亮led灯
5
<内核学习营>+坦然+探索者stm32f407板子RT-thread串口字符点灯
6
<内核学习营>+坦然+探索者stm32f407板子RT-thread的pwm点灯实验
7
<内核学习营>+坦然+探索者stm32f407板子RT-thread串口实验
8
<内核学习营>+坦然+野火stm32f103板子RT-thread读写SD卡实验
9
<内核学习营>+坦然+探索者stm32f407板子RT-thread的RTC闹钟实验
10
【内核学习营】+王秀峰+led_rgb
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
GD32F450 片内 flash驱动适配
2
STM32H7R7运行CherryUSB
3
RT-Smart首次线下培训,锁定2024 RT-Thread开发者大会!
4
使用RC522软件包驱动FM1722
5
常量数据类型和表达式陷阱分享
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
YZRD
2
篇文章
4
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部