Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
2024-RSOC
[2024-RSOC] IPC机制学习分享
发布于 2024-07-24 21:31:03 浏览:263
订阅该版
[tocm] # RT-Thread 暑期夏令营第三天:IPC机制学习心得 今天的培训主题是操作系统中的进程间通信(IPC)机制,特别是在RT-Thread中的实现和应用。通过对信号量、互斥量、事件集、邮箱和消息队列的原理和使用示例进行深入分析,进一步理解了线程同步和线程间通信的概念。以下是我今天学习的心得。 ## 1. 信号量 (Semaphore) 原理和示例分析 信号量是一种用于管理资源访问的同步机制。它通过一个计数器来记录资源的使用状态,当资源可用时,计数器增加;当资源被占用时,计数器减少。 - **原理**:信号量的计数器初始值通常设定为资源的数量。当线程申请资源时,如果计数器大于零,则申请成功,并将计数器减一;如果计数器等于零,则线程会进入等待状态,直到有其他线程释放资源。 - **示例**:[rtthread文档中心](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/ipc1/ipc1) ## 2. 互斥量 (Mutex) 原理和示例分析 互斥量是一种用于保护临界区资源的锁机制,它确保同一时刻只有一个线程能够访问资源。 - **原理**:互斥量初始状态是未锁定。当一个线程获取互斥量时,如果互斥量未被锁定,则锁定并进入临界区;如果互斥量已被锁定,则线程进入等待状态。持有互斥量的线程可以多次获取,但必须对应相同次数的释放操作。 - **示例**:[rtthread文档中心](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/ipc1/ipc1) ## 3. 事件集 (Event) 原理和示例分析 事件集是一种线程间通信机制,用于在特定条件下通知一个或多个线程。线程可以等待一个或多个事件的触发。 - **原理**:事件集由一组事件标志组成,线程可以等待这些标志的变化。事件可以是单个标志,也可以是多个标志的组合。 - **示例**:[rtthread文档中心](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/ipc1/ipc1) ## 4. 邮箱 (Mailbox) 原理和示例分析 邮箱是一种用于线程间发送固定大小消息的机制。它提供了一种简单的方式在线程间传递消息。 - **原理**:邮箱在创建时指定消息的大小和邮箱的容量。发送消息时,如果邮箱未满,则将消息存入邮箱;接收消息时,如果邮箱不为空,则取出消息。 - **示例**:[rtthread文档中心](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/ipc1/ipc1) ## 5. 消息队列 (MsgQueue) 原理和示例分析 消息队列是一种线程间传递变量大小消息的机制。它支持多线程之间发送和接收消息,提供了更灵活的通信方式。 - **原理**:消息队列在创建时指定消息的大小和队列的容量。发送消息时,如果队列未满,则将消息插入队列尾部;接收消息时,如果队列不为空,则取出队列头部的消息。 - **示例**:[rtthread文档中心](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/ipc1/ipc1) ## 6. 消息邮箱 (mailbox) 与消息队列 (msgqueue) 对比 - **消息邮箱**:每个消息的大小是固定的,适用于小数据量的传递。内存占用较少,性能较好。 - **消息队列**:消息大小可以变化,更灵活,适用于大数据量和变长数据的传递。内存占用较多,管理复杂。 ## 7. 各种 IPC 机制比较 - **使用信号量**:进行简单的资源管理和线程同步。 - **使用互斥量**:保护临界区,防止数据竞争。 - **使用事件集**:实现复杂的同步需求,特别是需要等待多个事件时。 - **使用邮箱和消息队列**:在线程间传递消息和数据。 ## 8. 作业 使用至少两种 IPC 编写试验代码: 下面代码使用三种 IPC 机制:使用 **信号量** 控制按键状态;使用 **互斥量** 保护 LED 灯的操作;使用 **消息队列** 传递按键消息。 ### 8.1. 全局变量和结构体 ```c static rt_thread_t tid1 = RT_NULL; static rt_thread_t tid2 = RT_NULL; static rt_thread_t tid3 = RT_NULL; static rt_sem_t dynamic_sem = RT_NULL; static rt_mutex_t led_mutex = RT_NULL; static rt_mq_t key_mq = RT_NULL; typedef struct { int key_val; } key_msg_t; ``` **说明**: - `tid1`、`tid2`、`tid3` 分别用于存储三个线程的句柄。 - `dynamic_sem`、`led_mutex` 和 `key_mq` 分别用于存储信号量、互斥量和消息队列的句柄。 - `key_msg_t` 结构体用于消息队列中传递按键值。 ### 8.2. 主函数 ```c int key_led(void) { // 初始化 LED 引脚 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; } rt_kprintf("create done. dynamic semaphore value = 0.\n"); // 创建互斥量 led_mutex = rt_mutex_create("ledmtx", RT_IPC_FLAG_PRIO); if (led_mutex == RT_NULL) { rt_kprintf("create led mutex failed.\n"); return -1; } // 创建消息队列 key_mq = rt_mq_create("keymq", sizeof(key_msg_t), 10, RT_IPC_FLAG_PRIO); if (key_mq == RT_NULL) { rt_kprintf("create key message queue failed.\n"); return -1; } // 创建线程 tid1 = rt_thread_create("key_thread", key_thread_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_thread_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); if (tid2 != RT_NULL) rt_thread_startup(tid2); tid3 = rt_thread_create("key_msg_thread", key_msg_thread_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY-2, THREAD_TIMESLICE); if (tid3 != RT_NULL) rt_thread_startup(tid3); return 0; } ``` **说明**: - 主函数负责初始化硬件引脚、创建信号量、互斥量和消息队列,并创建并启动三个线程。 ### 8.3. `key_thread_entry` 函数 ```c static void key_thread_entry(void *parameter) { 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); key_msg_t msg; msg.key_val = 1; rt_mq_send(key_mq, &msg, sizeof(msg)); } } rt_thread_mdelay(10); } } ``` **说明**: - `key_thread_entry` 线程函数检测按键状态。如果按键被按下(即 `PIN_KEY0` 读取为 `PIN_LOW`),则释放信号量,并将按键消息发送到消息队列中。 ### 8.4. `led_thread_entry` 函数 ```c static void led_thread_entry(void *parameter) { rt_uint32_t result; while (1) { result = rt_sem_take(dynamic_sem, RT_WAITING_FOREVER); if (result == RT_EOK) { rt_mutex_take(led_mutex, RT_WAITING_FOREVER); rt_pin_write(GPIO_LED_R, PIN_LOW); rt_kprintf("LED_R ON .\r\n"); rt_thread_mdelay(500); rt_pin_write(GPIO_LED_R, PIN_HIGH); rt_kprintf("LED_R OFF.\r\n"); rt_mutex_release(led_mutex); } } } ``` **说明**: - `led_thread_entry` 线程函数等待信号量的释放,获取互斥量来保护LED的操作,控制LED的开关状态。 ### 8.5. `key_msg_thread_entry` 函数 ```c static void key_msg_thread_entry(void *parameter) { key_msg_t msg; while (1) { if (rt_mq_recv(key_mq, &msg, sizeof(msg), RT_WAITING_FOREVER) == RT_EOK) { rt_kprintf("Key message received: %d\r\n", msg.key_val); } } } ``` **说明**: - `key_msg_thread_entry` 线程函数从消息队列中接收消息,并打印接收到的消息值。 ### 8.6. 实验结果 1.消息队列传按键按压数据 ![实验结果3.1](https://gitee.com/lishuangrui/test1/raw/master/figures/%E5%AE%9E%E9%AA%8C%E7%BB%93%E6%9E%9C3.1.png) 2.信号量和互斥保证点灯不受影响 ![实验结果红灯亮3.2](https://gitee.com/lishuangrui/test1/raw/master/figures/%E5%AE%9E%E9%AA%8C%E7%BB%93%E6%9E%9C%E7%BA%A2%E7%81%AF%E4%BA%AE3.2.png) ![实验结果红灯亮灭3.3](https://gitee.com/lishuangrui/test1/raw/master/figures/%E5%AE%9E%E9%AA%8C%E7%BB%93%E6%9E%9C%E7%BA%A2%E7%81%AF%E4%BA%AE%E7%81%AD3.3.png) ## 总结 通过这次学习,我对RT-Thread中各种IPC机制的应用有了更深入的理解。每种IPC机制都有其独特的用途和特点,合理使用这些机制可以有效地解决线程间的同步和通信问题。在实际开发中,根据不同的需求选择合适的IPC机制,将能提升系统的性能和可靠性。 ---
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
猪的行独
这家伙很懒,什么也没写!
文章
7
回答
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
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
xusiwei1236
8
个答案
2
次被采纳
踩姑娘的小蘑菇
1
个答案
2
次被采纳
用户名由3_15位
9
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
RTT_逍遥
3
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
15
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
4
次点赞
Ghost_Girls
1
篇文章
7
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部