Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
DIY综合交流区
[RealTouch例程]互斥量的基本使用
发布于 2012-08-17 09:15:20 浏览:5277
订阅该版
实验目的 ? 了解互斥量的基本使用,初始化,获取,释放互斥量,删除/脱离互斥量 ? 熟练使用互斥量相关API 硬件说明 本实验使用RT-Thread官方的Realtouch开发板作为实验平台。涉及到的硬件主要为: ? 串口3,作为rt_kprintf输出 需要连接JTAG扩展板,具体请参见《Realtouch开发板使用手册》 实验原理及程序结构 实验设计 本实验的主要设计目的是帮助读者快速了解互斥量相关API,包括静态互斥量初始化/脱离,动态互斥量创建/删除,互斥量获取/释放相关API。 源程序说明 本实验对应kernel_mutex_basic 系统依赖 在rtconfig.h中需要开启 ``` #define RT_USING_HEAP``` 此项可选,开启此项可以创建动态线程和动态互斥量,如果使用静态线程和静态互斥量,则此项不是必要的 ``` #define RT_USING_MUTEX``` 此项必须,开启此项后可以使用互斥量相关API。 ``` #define RT_USING_CONSOLE``` 此项必须,本实验使用rt_kprintf向串口打印按键信息,因此需要开启此项 主程序说明 在applications/application.c中定义一个两个全局变量,分别为静态互斥量数据结构和动态互斥量指针。 全局变量定义代码 ```/* 互斥量控制块 */ static struct rt_mutex static_mutex; /* 指向互斥量的指针 */ static rt_mutex_t dynamic_mutex = RT_NULL; ``` 在applications/application.c中的 int rt_application_init()函数中初始化一个静态互斥量和一个动态互斥量,如下所示 互斥量创建/初始化代码 ``` rt_err_t result; /* 初始化静态互斥量 */ result = rt_mutex_init(&static_mutex, "smutex", RT_IPC_FLAG_FIFO); if (result != RT_EOK) { rt_kprintf("init static mutex failed. "); return -1; } /* 创建一个动态互斥量 */ dynamic_mutex = rt_mutex_create("dmutex", RT_IPC_FLAG_FIFO); if (dynamic_mutex == RT_NULL) { rt_kprintf("create dynamic mutex failed. "); return -1; } ```在int rt_application_init()创建了两个线程1,分别成为线程1和线程2,如下所示。读者需要注意,线程2的优先级比线程1的优先级高。 初始化线程代码 ``` rt_thread_init(&thread1, "thread1", rt_thread_entry1, RT_NULL, &thread1_stack[0], sizeof(thread1_stack),11,5);//线程优先级11,时间片5 rt_thread_startup(&thread1); rt_thread_init(&thread2, "thread2", rt_thread_entry2, RT_NULL, &thread2_stack[0], sizeof(thread2_stack),10,5);//线程优先级10,时间片5 rt_thread_startup(&thread2); ``` 其线程处理函数如下所示。 线程1代码 ```ALIGN(RT_ALIGN_SIZE) //设置下一句线程栈数组为对齐地址 static char thread1_stack[1024]; //设置线程堆栈为1024Bytes struct rt_thread thread1; //定义静态线程数据结构 static void rt_thread_entry1(void* parameter) { rt_err_t result; rt_tick_t tick; /* 1. staic mutex demo */ /* 试图持有互斥量,最大等待10个OS Tick后返回 */ rt_kprintf("thread1 try to get static mutex, wait 10 ticks. "); /* 获得当前的OS Tick */ tick = rt_tick_get(); result = rt_mutex_take(&static_mutex, 10); if (result == -RT_ETIMEOUT) { /* 超时后判断是否刚好是10个OS Tick */ if (rt_tick_get() - tick != 10) { rt_mutex_detach(&static_mutex); return; } rt_kprintf("thread1 take static mutex timeout "); } else { /* 线程2持有互斥量,且在相当长的时间后才会释放互斥量, * 因此10个tick后线程1不可能获得 */ rt_kprintf("thread1 take a static mutex, failed. "); rt_mutex_detach(&static_mutex); return; } /* 永久等待方式持有互斥量 */ rt_kprintf("thread1 try to get static mutex, wait forever. "); result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER); if (result != RT_EOK) { /* 不成功则测试失败 */ rt_kprintf("thread1 take a static mutex, failed. "); rt_mutex_detach(&static_mutex); return; } rt_kprintf("thread1 take a staic mutex, done. "); /* 脱离互斥量对象 */ rt_mutex_detach(&static_mutex); /* 2. dynamic mutex test */ /* 试图持有互斥量,最大等待10个OS Tick后返回 */ rt_kprintf("thread1 try to get dynamic mutex, wait 10 ticks. "); tick = rt_tick_get(); result = rt_mutex_take(dynamic_mutex, 10); if (result == -RT_ETIMEOUT) { /* 超时后判断是否刚好是10个OS Tick */ if (rt_tick_get() - tick != 10) { rt_mutex_delete(dynamic_mutex); return; } rt_kprintf("thread1 take dynamic mutex timeout "); } else { /* 线程2持有互斥量,且在相当长的时间后才会释放互斥量, * 因此10个tick后线程1不可能获得 */ rt_kprintf("thread1 take a dynamic mutex, failed. "); rt_mutex_delete(dynamic_mutex); return; } /* 永久等待方式持有互斥量 */ rt_kprintf("thread1 try to get dynamic mutex, wait forever. "); result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER); if (result != RT_EOK) { /* 不成功则测试失败 */ rt_kprintf("thread1 take a dynamic mutex, failed. "); rt_mutex_delete(dynamic_mutex); return; } rt_kprintf("thread1 take a dynamic mutex, done. "); /* 删除互斥量对象 */ rt_mutex_delete(dynamic_mutex); }``` 线程2的入口函数如下所示 线程2代码 ```ALIGN(RT_ALIGN_SIZE) static char thread2_stack[1024]; struct rt_thread thread2; static void rt_thread_entry2(void* parameter) { rt_err_t result; rt_tick_t tick; /* 1. static mutex test */ rt_kprintf("thread2 try to get static mutex "); rt_mutex_take(&static_mutex, 10); rt_kprintf("thread2 got static mutex "); rt_thread_delay(RT_TICK_PER_SECOND); rt_kprintf("thread2 release static mutex "); rt_mutex_release(&static_mutex); /* 2. dynamic mutex test */ rt_kprintf("thread2 try to get dynamic mutex "); rt_mutex_take(dynamic_mutex, 10); rt_kprintf("thread2 got dynamic mutex "); rt_thread_delay(RT_TICK_PER_SECOND); rt_kprintf("thread2 release dynamic mutex "); rt_mutex_release(dynamic_mutex); }``` 编译调试及观察输出信息 编译请参见《RT-Thread配置开发环境指南》完成编译烧录,参考《Realtouch开发板使用手册》完成硬件连接,连接扩展板上的串口和jlink。 运行后可以看到如下信息: 串口输出信息 ``` | / - RT - Thread Operating System / | 1.1.0 build Aug 9 2012 2006 - 2012 Copyright by rt-thread team thread2 try to get static mutex thread2 got static mutex thread1 try to get static mutex, wait 10 ticks. thread1 take static mutex timeout thread1 try to get static mutex, wait forever. thread2 release static mutex thread2 try to get dynamic mutex thread2 got dynamic mutex thread1 take a staic mutex, done. thread1 try to get dynamic mutex, wait 10 ticks. thread1 take dynamic mutex timeout thread1 try to get dynamic mutex, wait forever. thread2 release dynamic mutex thread1 take a dynamic mutex, done.``` 结果分析 整个程序运行过程中各个线程的状态变化: rt_application_init中创建线程thread1和线程thread2,这两个线程相互获取和释放互斥量来完成信号量的基本测试。由于动态互斥量和静态互斥量的测试过程基本一致,因此这里重点分析静态互斥量的测试过程。 由于thread2的优先级高于线程1的优先级,因此thread2先运行,在其线程处理函数中先获取static_mutex,并打印信息 ```thread2 try to get static mutex thread2 got static mutex``` 随后thread2休眠1秒钟,线程2被挂起,线程1调度运行。在线程1中试图持有static_mutex,并设定等待时间为10个tick,此时static_mutex依然被处于挂起中的线程2所持有,因此线程1会被挂起。这个过程中打印信息为: ```thread1 try to get static mutex, wait 10 ticks. thread1 take static mutex timeout``` 内核调度IDLE线程执行,10个tick后,线程1依然无法拿到staic_mutex,等待超时,线程1再次被唤醒。接下来线程1试图使用 result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER); 这会永久等待信号量static_mutex。 打印信息为 thread1 try to get static mutex, wait forever. 线程1会被一直挂起。此时内核调度IDLE线程执行 大约1秒后,线程2被唤醒立刻抢占IDLE线程并运行,释放static_mutex,线程1被唤醒,状态变为就绪态,但由于线程1优先级低于线程2,因此线程2继续运行,获取动态信号量,这个过程打印如下信息: ```thread2 release static mutex thread2 try to get dynamic mutex thread2 got dynamic mutex``` 接下来线程2再次休眠1秒钟,之后的过程跟前面的过程类似,就留给读者分析。 总结 本实验演示了RT-Thread中互斥量的API的基本使用,对于静态互斥量,使用init/detach来初始化和脱离,对用动态互斥量使用create/delete来创建删除。take/release中的第一个参数为指针,因此当时使用静态互斥量时,需要取去地址符号&,读者需要注意 [attach]0[/attach] 下载附件 [实验2_6互斥量基本使用.pdf](https://oss-club.rt-thread.org/uploads/88_1d8dbd6c48529347bc777a3553382ff5.pdf) 下载附件 [1_kernel_mutex_basic.zip](https://oss-club.rt-thread.org/uploads/3089_0ab87e5ce4b9dd3ff450779b5d8862d6.zip)
查看更多
2
个回答
默认排序
按发布时间排序
bloom5
2012-09-05
这家伙很懒,什么也没写!
添加例程 [attach]1282[/attach]
撰写答案
登录
注册新账号
关注者
0
被浏览
5.3k
关于作者
shaolin
这家伙很懒,什么也没写!
提问
115
回答
444
被采纳
0
关注TA
发私信
相关问题
1
[项目]搞个开源的硬件项目
2
硬件计划贴,及时更新,欢迎提意见
3
软件计划贴,及时更新,欢迎提意见::WMA,MOUNT,LWIP等问题急需解决.
4
MMS协议
5
定点的wma解压库-libwma
6
QQ群记录 [20090821]
7
STM32网络收音机PCB报名征集
8
第一版调试记录
9
第二版硬件讨论
10
RADIO项目相关模块规格--欢迎大家自己做板时规格与此兼容,减少重复劳动
推荐文章
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
在RT-Thread Studio中构建前执行python命令
2
研究一了一段时间RTT,直接标准版上手太难,想用nano,但又舍不得组件
3
CherryUSB开发笔记(一):FSDEV USB IP核的 HID Remote WakeUp (USB HID 远程唤醒) 2025-01-18 V1.1
4
RT-thread 缩写字典
5
RT Thread 源码分析笔记 :线程和调度器
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
Bootloader
AT
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在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
用户名由3_15位
7
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
xusiwei1236
4
个答案
1
次被采纳
踩姑娘的小蘑菇
1
个答案
1
次被采纳
张世争
1
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
14
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
2
次点赞
Ghost_Girls
1
篇文章
6
次点赞
xiaorui
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部