Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
2024-RSOC
【2024-RSOC】DAY3 IPC机制的学习
发布于 2024-08-02 15:41:27 浏览:114
订阅该版
[tocm] # 【2024-RSOC】DAY3 IPC机制的学习 ## 学习内容 今天主要学习了RT-Thread的IPC机制 线程间同步的信号量、互斥量以及事件集; 线程间通信的邮箱和消息队列; ## 概念介绍 ### 线程同步 #### 信号量 以生活中的停车场为例来理解信号量的概念: ①当停车场空的时候,停车场的管理员发现有很多空车位,此时会让外面的车陆续进入停车场获得停车位; ②当停车场的车位满的时候,管理员发现已经没有空车位,将禁止外面的车进入停车场,车辆在外排队等候; ③当停车场内有车离开时,管理员发现有空的车位让出,允许外面的车进入停车场;待空车位填满后,又禁止外部车辆进入。 在此例子中,管理员就相当于信号量,管理员手中空车位的个数就是信号量的值(非负数,动态变化);停车位相当于公共资源(临界区),车辆相当于线程。车辆通过获得管理员的允许取得停车位,就类似于线程通过获得信号量访问公共资源。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/95da1742efad49ad0e8eb587300f5bb6.png) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/0fc7f784fe2025b418fd4ef5242d38a4.png.webp) #### 互斥量 互斥量又叫相互排斥的信号量,是一种特殊的二值信号量。互斥量类似于只有一个车位的停车场:当有一辆车进入的时候,将停车场大门锁住,其他车辆在外面等候。当里面的车出来时,将停车场大门打开,下一辆车才可以进入。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/f4851abb25c84eefe88a35c0d05df948.png) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/7e46db5d2bac6faf1f3d63d5d89f24d8.png.webp) #### 事件集 事件集也是线程间同步的机制之一,一个事件集可以包含多个事件,利用事件集可以完成一对多,多对多的线程间同步。下面以坐公交为例说明事件,在公交站等公交时可能有以下几种情况: ①P1 坐公交去某地,只有一种公交可以到达目的地,等到此公交即可出发。 ②P1 坐公交去某地,有 3 种公交都可以到达目的地,等到其中任意一辆即可出发。 ③P1 约另一人 P2 一起去某地,则 P1 必须要等到 “同伴 P2 到达公交站” 与“公交到达公交站”两个条件都满足后,才能出发。 这里,可以将 P1 去某地视为线程,将 “公交到达公交站”、“同伴 P2 到达公交站” 视为事件的发生,情况①是特定事件唤醒线程;情况②是任意单个事件唤醒线程;情况③是多个事件同时发生才唤醒线程。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/10a295867a9519e35e91c9ac57dcd8bc.png) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/6e57eed86ba9fad6839ff521f8c76531.png.webp) ### 线程通信 #### 邮箱 邮箱服务是实时操作系统中一种典型的线程间通信方法。举一个简单的例子,有两个线程,线程 1 检测按键状态并发送,线程 2 读取按键状态并根据按键的状态相应地改变 LED 的亮灭。这里就可以使用邮箱的方式进行通信,线程 1 将按键的状态作为邮件发送到邮箱,线程 2 在邮箱中读取邮件获得按键状态并对 LED 执行亮灭操作。 这里的线程 1 也可以扩展为多个线程。例如,共有三个线程,线程 1 检测并发送按键状态,线程 2 检测并发送 ADC 采样信息,线程 3 则根据接收的信息类型不同,执行不同的操作。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/92a3f0c2bd1894c1d91c594af1f9a570.png) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/627250e2d7b3a19d7c2cb5497170a386.png.webp) #### 消息队列 消息队列是另一种常用的线程间通讯方式,是邮箱的扩展。可以应用在多种场合:线程间的消息交换、使用串口接收不定长数据等。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/d0f14bb2c613615e89bc18469996af8b.png) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/8affb9d1d703385c4589d1b3fe725d27.png.webp) ## 代码示例 ```c #include
#include
#include
#ifndef RT_USING_NANO #include
#endif /* RT_USING_NANO */ #define PIN_KEY0 GET_PIN(C, 0) //PC0: KEY0 #define GPIO_LED_B GET_PIN(F, 11) #define GPIO_LED_R GET_PIN(F, 12) #define THREAD_PRIORITY 25 #define THREAD_STACK_SIZE 1024 #define THREAD_TIMESLICE 5 static rt_thread_t tid1 = RT_NULL; static rt_thread_t tid2 = RT_NULL; static rt_sem_t dynamic_sem = RT_NULL; static void key_name_entry(void *parameter); static void led_name_entry(void *parameter); int main(void) { rt_pin_mode(GPIO_LED_R, PIN_MODE_OUTPUT); rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP); dynamic_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_PRIO); if( dynamic_sem = RT_NULL) { rt_kprintf("create dynamic semaphore failed.\n"); return -1; } else { rt_kprintf("create done. dynamic semaphore value = 0. \n"); } tid1 = rt_thread_create("key_thread", key_name_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); if (tid1 != RT_NULL) rt_thread_startup(tid1); tid2 = rt_thread_create("led_thread", led_name_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); if (tid2 != RT_NULL) rt_thread_startup(tid2); /* while (1) { rt_pin_write(GPIO_LED_R, PIN_HIGH); rt_thread_mdelay(500); rt_pin_write(GPIO_LED_R, PIN_LOW); rt_thread_mdelay(500); } */ } static void key_name_entry(void *parameter) { rt_uint32_t count = 0; while (1) { if (rt_pin_read(PIN_KEY0) == PIN_LOW) { rt_thread_mdelay(100); if (rt_pin_read(PIN_KEY0) == PIN_LOW) { rt_kprintf("KEY0 pressed!\r\n"); rt_sem_release(dynamic_sem); } } rt_thread_mdelay(10); } } static void led_name_entry(void *parameter) { rt_uint32_t result = 0; while (1) { result = rt_sem_take(dynamic_sem, RT_WAITING_FOREVER); if (result == RT_EOK) { rt_kprintf("LED HIGH\r\n"); rt_pin_write(GPIO_LED_R, PIN_HIGH); } else { rt_kprintf("LED LOW\r\n"); rt_pin_write(GPIO_LED_R, PIN_LOW); } } } ``` ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/123bb934e7e18398c52f84219881a7d0.png.webp) ## 在线下载软件包 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/a20a87f7a3007e4d1954b8dcf8ef7c9d.png.webp) ```c menuconfig.exe ``` 编译后 ```c pkgs --update ``` 烧录完成 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240802/15fc5253f75f33b60a8af8cd1698d1d6.png.webp)
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
cy_99
这家伙很懒,什么也没写!
文章
3
回答
0
被采纳
0
关注TA
发私信
相关文章
推荐文章
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组件
热门标签
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
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
MicroPython
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
19
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
6
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
RTT_逍遥
1
篇文章
5
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部