OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 15010|回复: 21

uCOSIII例程中 例10-2 UCOSIII使用信号量访问共享资源区 的代码中有理解不透彻的地方,还望赐教

[复制链接]

9

主题

93

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2016-5-4
在线时间
58 小时
发表于 2017-8-17 23:44:58 | 显示全部楼层 |阅读模式
1金钱
任务1和任务2的函数当中:

QQ图片20170817232533.png

在此例程中,任务1的优先级是4,任务2的优先级是5,任务1优先级高于任务2,按照我的理解,任务开始后,
首先执行任务1,173行,打印字符串,printf("\r\n任务1:\r\n");
接下来按顺序执行到175行,请求信号量,由于信号量创建时初始值是1,执行完这一行之后信号量变成0并且继续执行下去无需等待
接下来按顺序执行到177行,delay_ms(300);引起任务切换,切换到任务2
开始进入任务2,按顺序执行到192行,打印字符串,printf("\r\n任务2:\r\n");
接下来按顺序执行到194行,请求信号量,此时任务阻塞
待任务1的延时结束后,继续从178行开始执行,打印字符串,printf("%s\r\n",share_resource);
接下来按顺序执行到179行,发送信号量
紧接着任务2中的194行等待信号量已经等待完毕,接着执行
按顺序执行到197行,打印字符串,printf("%s\r\n",share_resource);
接下来按顺序执行到198行,发送信号量

第一个过程到此结束,按照预想此时串口接收到的数据应当是(花括号内的内容):
{
任务1:

任务2:
First task Running!
Second task Running!

}
到此没有问题,现象和预想的一样,接下来疑惑在下方。

任务2执行完之后,继续回到任务1,任务1从头开始运行直到175行请求信号量,由于刚才的任务2已经发送了信号量
所以此时信号量通过无需阻塞,将信号量减1变为0之后继续执行下去。直到177行,任务延时delay_ms(300);引发任务调度。
那么此时应该是切换到任务2,任务2从头开始执行,经过192行打印出printf("\r\n任务2:\r\n");
之后遇到194行,请求信号量,阻塞在此。
待任务1延时结束后,打印printf("%s\r\n",share_resource);之后紧接着发送信号量,然后任务2继续执行下去,打印printf("%s\r\n",share_resource);


OK疑点在此,按照上述分析,任务1发送完printf("\r\n任务1:\r\n");之后,(176行请求信号量通过)在177行处引发调度,执行任务2,打印完printf("\r\n任务2:\r\n");之后,才开始遇到请求信号量。
按照预想, 串口接收到的数据应该是“\r\n任务1:\r\n”和“\r\n任务2:\r\n”紧接在一起的,也就是:
{
任务1:

任务2:

First task Running!
Second task Running!
}
然而现象是:
{
任务1:
First task Running!

任务2:
Second task Running!

}

为什么会这样呢,为什么第一轮和预想的一样,第二轮开始就成了这样了呢,是否是我程序分析得不对?
困扰多时,还望原子哥和左前辈还有各位大牛解我之惑,感激之至。

最佳答案

查看完整内容[请看2#楼]

非常感谢@yanzhuangsongqi 所提到的1S延时,一语点醒梦中人,关键就在于这个1S延时当中。 问题基本明朗了,我原文中分析错误的地方在于: 接下来按顺序执行到179行,发送信号量 紧接着任务2中的194行等待信号量已经等待完毕,接着执行 179行发送完信号量后,根据OSSemPost()函数的描述,“如果有一个或多个任务在等待这个信号量,则优先级最高的任务将获得这个信号量,然后由调度器来判定刚获得信号量的任务是否为系统中 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

93

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2016-5-4
在线时间
58 小时
 楼主| 发表于 2017-8-17 23:44:59 | 显示全部楼层
非常感谢@yanzhuangsongqi 所提到的1S延时,一语点醒梦中人,关键就在于这个1S延时当中。
问题基本明朗了,我原文中分析错误的地方在于:

接下来按顺序执行到179行,发送信号量
紧接着任务2中的194行等待信号量已经等待完毕,接着执行



179行发送完信号量后,根据OSSemPost()函数的描述,“如果有一个或多个任务在等待这个信号量,则优先级最高的任务将获得这个信号量,然后由调度器来判定刚获得信号量的任务是否为系统中优先级最高的就绪任务,如果是,则系统将进行任务切换,运行这个就绪的任务。”
也就是说,发送完信号量之后,任务2虽然获得了这个信号量,但是它优先级是5,而任务1优先级是4,也就是任务1会继续执行下去而不是发送信号量之后马上就切换到任务2了,而是一直运行下去直到181行延时1s。

遇到181行,任务1开始延时,发生任务切换,此时切换到任务2的194行,信号量已获得继续执行下去,直到196行开始延时300ms,由于其他任务也在延时,因此任务没有切换。300ms过后(特别注意,由于延时是同时进行的,所以此时任务1已经延时了>=300ms,它只剩下<=700ms的延时),任务2继续执行,通过197行打印字符串、198行发送信号量(此时不发生任务切换)后直到200行,任务2开始延时1S(特别注意,此时任务1已经延时了超过300ms,具体多少可能是302ms或者303、304ms,也就是它大约只剩下698ms延时,请注意这个超出的2~3ms是关键)。此时两个任务同时延时,此时任务1约剩下698ms延时,任务2剩余1000ms延时。

698ms(也可能是697ms或者699ms)过后,任务1延时结束,它获得CPU使用权继续执行,(此时任务2大约还有302ms(也可能是301ms或者303ms)左右),任务1从173行开始依次执行,直到177行代码,开始延时300ms。(重点来了,当任务1开始要延时300ms的时候,任务2还在那个1s的延时当中,它还剩下大约302ms或者301ms左右,也就是最终任务1还是先比它早2ms左右结束延时),300ms过后,任务1延时结束,而任务2还剩下大约1~2ms的延时,于是任务1继续执行,执行178行打印"First task Running!"。OK这就是为什么随后现象是:
{
任务1:
First task Running!

任务2:
Second task Running!
}
那时因为任务1延时300ms过后,任务2还在它的1s延时当中。

OK问题到此结束,本次问题的关键点在于:
1、OSSemPost()执行完之后是否发生任务切换还要根据获得信号量的那个任务的优先级是否高于当前执行的任务优先级。
2、UCOS的实时性真的很强,就算只有1~2ms的差距,也会影响任务的执行优先顺序。
回复

使用道具 举报

88

主题

7381

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14979
金钱
14979
注册时间
2013-11-13
在线时间
1823 小时
发表于 2017-8-18 09:05:38 | 显示全部楼层
这个分析起来确实太绕了,只能提示你要考虑各种会引起任务调度的地方。
回复

使用道具 举报

9

主题

93

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2016-5-4
在线时间
58 小时
 楼主| 发表于 2017-8-18 15:05:16 | 显示全部楼层
zuozhongkai 发表于 2017-8-18 09:05
这个分析起来确实太绕了,只能提示你要考虑各种会引起任务调度的地方。

好的,那我先搁置,说不定往后学之后这个问题就能清晰明朗
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
6
金钱
6
注册时间
2017-5-28
在线时间
1 小时
发表于 2017-8-20 11:39:03 | 显示全部楼层
请问楼主问题解决了没?
回复

使用道具 举报

9

主题

93

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2016-5-4
在线时间
58 小时
 楼主| 发表于 2017-8-20 14:26:56 | 显示全部楼层
13144096602 发表于 2017-8-20 11:39
请问楼主问题解决了没?

还没有呢
回复

使用道具 举报

18

主题

151

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3783
金钱
3783
注册时间
2016-7-8
在线时间
804 小时
发表于 2017-8-21 08:57:45 | 显示全部楼层
是不是函数最后的1s延时导致的?
回复

使用道具 举报

9

主题

93

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2016-5-4
在线时间
58 小时
 楼主| 发表于 2017-8-21 11:19:54 | 显示全部楼层
yanzhuangsongqi 发表于 2017-8-21 08:57
是不是函数最后的1s延时导致的?

把两个任务的1S延时都注释掉,现象依然不变
回复

使用道具 举报

18

主题

151

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3783
金钱
3783
注册时间
2016-7-8
在线时间
804 小时
发表于 2017-8-21 12:58:16 | 显示全部楼层
分析的很透彻
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2016-4-20
在线时间
6 小时
发表于 2017-12-16 12:33:11 | 显示全部楼层
飘逸心晴 发表于 2017-8-21 11:19
把两个任务的1S延时都注释掉,现象依然不变

变了,任务1的printf 在任务2中进行,任务2的printf在任务1中进行!楼主分析的很对,delay_ms(300)与系统延时1s的搭配才可以保证每一个任务能完整的进行,而不是一会任务1分配,然后任务2打印,再任务1分配,再任务2打印这样就乱套了!
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2016-4-20
在线时间
6 小时
发表于 2017-12-16 12:51:08 | 显示全部楼层
实际上,你可以用SWD硬件仿真一下,就可以看到真实的运行情况,而不是自己主观的去推理。我刚才仿真了一下,OSSemPost()只是发送一个信号量,他没有权力去任务调度,只能等到系统延时才可以去任务调度。
回复

使用道具 举报

14

主题

94

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
362
金钱
362
注册时间
2017-10-2
在线时间
80 小时
发表于 2018-4-13 19:17:11 | 显示全部楼层
本帖最后由 a0101 于 2018-4-13 19:21 编辑

老哥你好,我想问一下在执行完OSSemPend( )函数后delay_ms(300);的任务调度是不是不能用了?如果能的话,在串口调试助手上看到的是任务1: 任务2几乎同时被打印出来,等0.3秒后打印first task running和secondt task running.
回复

使用道具 举报

14

主题

94

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
362
金钱
362
注册时间
2017-10-2
在线时间
80 小时
发表于 2018-4-13 20:40:48 | 显示全部楼层
a0101 发表于 2018-4-13 19:17
老哥你好,我想问一下在执行完OSSemPend( )函数后delay_ms(300);的任务调度是不是不能用了?如果能的话,在 ...

我明白了,这是第一次执行的情况,以后的就和老哥说的一样了。
回复

使用道具 举报

18

主题

62

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
271
金钱
271
注册时间
2017-3-27
在线时间
76 小时
发表于 2018-4-13 21:28:20 | 显示全部楼层
66666666
回复

使用道具 举报

0

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2017-10-25
在线时间
30 小时
发表于 2018-5-25 09:31:24 | 显示全部楼层
其实是任务阻塞了,才导致delay_ms()不能调度的
回复

使用道具 举报

1

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
63
金钱
63
注册时间
2016-7-18
在线时间
12 小时
发表于 2020-1-10 09:52:45 | 显示全部楼层
信号量  分析得很透彻
回复

使用道具 举报

24

主题

113

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
219
金钱
219
注册时间
2019-11-8
在线时间
62 小时
发表于 2020-1-16 15:34:47 | 显示全部楼层
楼主提供的这个帖子让我这个初步接触ucos的小白豁然开朗
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2019-11-30
在线时间
8 小时
发表于 2020-1-23 19:19:36 | 显示全部楼层
受益匪浅   多谢
回复

使用道具 举报

0

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2020-12-31
在线时间
27 小时
发表于 2021-5-31 11:20:14 | 显示全部楼层
强强强!!!刚入门,这样的分析太需要了!!!
回复

使用道具 举报

1

主题

2

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2020-11-5
在线时间
9 小时
发表于 2021-7-29 01:50:31 | 显示全部楼层
其实还有一种情况,两个task中的delay_ms()时长不同,则不管后面的1s延时,仍然会在各自delay_ms()中发生任务调度,比如task1用delay_ms(400)和task2用delay_ms(200);还有另一种情况,假设仍然都是delay_ms(200),但是在task1中debug到这条函数之后设置断点,你会发线task2莫名其妙的进入了就绪列表,如果此时再在此处加个delay_ms(200)(也就是task11连续两个delay(200),task2保持一个delay(200)),就会发生任务调度。。。仍然不知何解。。。
回复

使用道具 举报

0

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
98
金钱
98
注册时间
2019-3-9
在线时间
28 小时
发表于 2022-1-12 15:29:46 | 显示全部楼层
受教了,UCOS看来还得涉及时间管理
回复

使用道具 举报

0

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
74
金钱
74
注册时间
2022-4-8
在线时间
16 小时
发表于 2022-4-19 17:36:19 | 显示全部楼层
刚学习UCOSIII看到楼主这篇文章,解决了我的一些疑惑,同时我也分享一下我的理解,对于后续的输出,因为任务2delay的时候,任务1处于挂起状态(1s延时),所以任务2延时结束之前没有其他任务运行,所以任务2能完成输出,一切源于UCOS的时间管理,两个任务切换的延时都是1s,这个时间大于任务1和任务2的运行总时,因此后续的输出是任务1任务2各能完整输出。然后根据楼主的分析,我把任务一的切换延时改为了304ms,任务2切换延时改为302ms,串口的输出变为和之前相同,任务1的切换延时理论上大于303都会切换,但是任务1优先级高于任务2,延时过大会在任务2运行时抢占,这也验证了我的理解。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-6-10 03:04

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表