Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
DIY综合交流区
[RealTouch例程]线程抢占导致临界区问题
发布于 2012-08-15 21:41:40 浏览:8844
订阅该版
实验目的 ? 了解多线程环境中的临界区问题 硬件说明 本实验使用RT-Thread官方的Realtouch开发板作为实验平台。 涉及到的硬件主要有: ? 串口3,作为rt_kprintf输出,需要连接JTAG扩展板 具体请参见《Realtouch开发板使用手册》 实验原理及程序结构 实验设计 临界资源是指一次仅允许一个线程使用的共享资源。不论是硬件临界资源,还是软件临界资源,多个线程必须互斥地对它们进行访问。 每个线程中访问临界资源的那段代码称为临界区(Critical Section),每次只准许一个线程进入临界区,进入后不允许其他线程进入。 多线程程序的开发方式不同于裸机程序,多个线程在宏观上是并发运行的,因此使用一个共享资源是需要注意,否则就可能出现错误的运行结果。 本实验通过一个简单的共享变量来演示多线程中的临界区问题。 源程序说明 本实验对应kernel_critial_region。 系统依赖 在rtconfig.h中需要开启 ``` #define RT_USING_HEAP``` 此项可选,开启此项可以创建动态线程,如果使用静态线程,则此项不是必要的 ``` #define RT_USING_CONSOLE``` 此项必须,本实验使用rt_kpriintf向串口打印按键信息,因此需要开启此项 ``` #define RT_TICK_PER_SECOND 10000``` 主程序说明 在applications/application.c中定义一个全局变量为 定义全局变量 ```static int share_var;``` 在applications/application.c中的 int rt_application_init()函数中初始化名为”thread1”的thread1的静态线程,如下所示。 创建线程代码 ``` int rt_application_init() { rt_thread_init(&thread1, "thread1", rt_thread_entry1, RT_NULL, &thread1_stack[0], sizeof(thread1_stack),11,5); rt_thread_startup(&thread1); rt_thread_init(&thread2, "thread2", rt_thread_entry2, RT_NULL, &thread2_stack[0], sizeof(thread2_stack),10,5); rt_thread_startup(&thread2); return 0; }``` 其线程处理函数如下所示,在线程处理函数中,首先调用rt_kprintf向串口打印共享变量的值,然后接下来的for循环代码来模拟对贡献变量的share_var的处理算法,注意这里为了增加这个“算法”的运行时间,使用for循环对share_var做了100000次累加操作。“算法”运行完毕后,再次使用rt_kprintf将共享变量的值打印。 线程1代码 ```ALIGN(RT_ALIGN_SIZE) //设置下一句线程栈数组为对齐地址 static char thread1_stack[1024];//设置线程堆栈为1024Bytes struct rt_thread thread1; //定义静态线程数据结构 static void rt_thread_entry1(void* parameter) { int i; share_var = 0; rt_kprintf("share_var = %d ", share_var); //模拟算法 for(i=0; i<100000; i++) { share_var ++; } rt_kprintf(" share_var = %d ", share_var); }``` 接下来在创建线程2,代码如下所示,在线程处理函数中,先调用rt_thread_delay休眠1个系统tick,然后对共享变量share_var的值做一次累加,之后线程处理函数运行完毕。 线程2代码 ```ALIGN(RT_ALIGN_SIZE) //设置下一句线程栈数组为对齐地址 static char thread1_stack[1024]; //设置线程堆栈为1024Bytes struct rt_thread thread1; //定义静态线程数据结构 static void rt_thread_entry2(void* parameter) { rt_thread_delay(1); share_var ++; }``` 编译调试及观察输出信息 编译请参见《RT-Thread配置开发环境指南》完成编译烧录,参考《Realtouch开发板使用手册》完成硬件连接,连接扩展板上的串口和jlink。 运行后可以看到如下信息。 串口输出 ``` | / - RT - Thread Operating System / | 1.1.0 build Aug 6 2012 2006 - 2012 Copyright by rt-thread team share_var = 0 share_var = 100001``` 修改线程2中的rt_thread_delay(1),为rt_thread_delay(1000); 再次烧录运行,输入结果如下所示。 串口输出 ``` | / - RT - Thread Operating System / | 1.1.0 build Aug 6 2012 2006 - 2012 Copyright by rt-thread team share_var = 0 share_var = 100000``` 结果分析 为什么会出现上面的结果呢?在for循环中我们对i做了100000次累加,如果没有其他线程的“干预”,那么共享变量的值应该是100000,现在的输出结果是100001,这意味这在打共享变量的值发生了变化,这个值是在线程2中修改的。 整个程序运行过程中各个线程的状态变化: rt_application_init中创建两个线程之后,由于线程2的优先级比线程1的优先级高,因此线程2先运行,其线程处理函数第一句为 rt_thread_delay(1) 这会使得线程2被挂起,挂起时间为1个tick,在线程2挂起的这段时间中,线程1是所有就绪态线程中优先级最高的线程,因此被内核调度运行,在其处理函数中执行,在线程1的处理函数执行了一部分代码后,1个tick时间到,线程1被唤醒,从而成为所有就绪线程中优先级最高的线程,因此会被立刻调度运行,线程1被线程2抢占,线程2处理函数中对贡献变量share_var做累加操作,接下来线程处理函数执行完毕,线程1再次被调度运行,根据程序的运行结果可以看出,此时线程1继续执行,但是我们并不知道此时线程1大致是从什么地方执行的,从最后的输出结果来看,只能得知此时线程1还没有执行到第二条rt_kprintf 输出语句。最后线程处理函数的最后打印共享变量的值,其值就应该是100001。 当修改了线程的休眠时间为1000个tick后,在线程休眠的整个事件内,线程2都已经执行完毕,因此最后的输出结果为100000。 可以看到当共享变量share_var在多个线程中公用时,如果缺乏必要的保护错误,最后的输出结果可能与预期的结果完全不同。为了解决这种问题,需要引入线程间通信机制,这就是所谓的IPC机制(Inter-Process Communication)。 总结 本实验演示了多任务环境中线程的临界区问题。 ![1_kernel_memory_mempool.zip](/uploads/88_5f2d67829322ef88401b1f209fa49c00.zip) ![1_kernel_critial_region.zip](/uploads/88_a2b9c1462caa8bde441fcc31a0e8e484.zip) 下载附件 [实验2_1线程抢占导致临界区问题.pdf](https://oss-club.rt-thread.org/uploads/88_3665d75ae8c22cb808d3150f74709bdf.pdf) 下载附件 [实验2_1线程抢占导致临界区问题.pdf](https://oss-club.rt-thread.org/uploads/3230_7f1b92baf49585dfcb53c963e6e9c896.pdf)
查看更多
9
个回答
默认排序
按发布时间排序
咖啡恋
2012-08-24
这家伙很懒,什么也没写!
“rt_application_init中创建两个线程之后,由于线程2的优先级比线程1的优先级高,因此线程2先运行,其线程处理函数第一句为” 这是我摘录的原文,上面提到线程2的优先级比线程1的优先级高,但是线程1和线程2在创建的时候,时间片和优先级都相同的情况下,如何判断线程2的优先级更高?
bernard
2012-08-24
这家伙很懒,什么也没写!
优先级都相同了为什么还要去判断线程2的优先级更高?
xinghui_fly
2012-08-27
这家伙很懒,什么也没写!
程序中设置的是相同的优先级和时间片,在说明中线程2的优先级比线程1的优先级高呢?怎么区分?请赐教 谢谢
shaolin
2012-08-27
这家伙很懒,什么也没写!
恩,这部分描述可能有误,多谢指出,请 prife 来看下吧。
prife
2012-08-27
这家伙很懒,什么也没写!
回复楼主: 是文档中写错了,实际上代码中,线程2的优先级是10,线程1的优先级是11...文档中写错了。 实际的源码在这里。 [https://github.com/RT-Thread/realtouch-stm32f4/blob/master/software/examples/examples/1_kernel_critial_region/applications/application.c](https://github.com/RT-Thread/realtouch- ... lication.c)
shaolin
2012-08-28
这家伙很懒,什么也没写!
增加了例程代码。
weiyuliang
2013-02-17
这家伙很懒,什么也没写!
在教程中摘录的 在线程1 的处理函数执行了一部分代码后,1 个tick 时间到,**线程1 被唤醒**,从而成为所有就绪线程中优先级最高的线 程,因此会被立刻调度运行,线程1 被线程2 抢占, 线程1 被唤醒,此处是否应该的线程2被唤醒那?
okwh
2019-02-14
这家伙很懒,什么也没写!
如何 让当前线程 临时独占MPU ? 用挂起调度器?
撰写答案
登录
注册新账号
关注者
0
被浏览
8.8k
关于作者
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
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部