OpenEdv-开源电子网

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

uCOS II的信号量及任务优先级问题求助。

[复制链接]

26

主题

186

帖子

0

精华

高级会员

Rank: 4

积分
810
金钱
810
注册时间
2014-5-30
在线时间
93 小时
发表于 2015-1-19 18:16:33 | 显示全部楼层 |阅读模式
5金钱
我用ucos建立了2个任务,任务1的优先级为2,任务2的优先级为3.

新建了一个信号量,初始值为1.

哪位能给你解惑一下:
1、任务1输出3,信号量发出后,为什么任务2没有执行呢?而是任务1把4和0输出,且把自己挂起后才执行任务2呢?
2、任务1把自己挂起时,那时信号量为1,他的优先级比任务2的高(任务2已经就绪,任务1也就绪了呀),应该是任务1继续
    执行的,为什么任务2却执行了?

下面是串口输出的语句:下面3行特意做了换行,原本这里是没有换行的
012534067
8129534067
8129534067



[mw_shl_code=c,true]/*****************************任务1*****************************************/ static void Task1 (void *p_arg) { INT8U err; while(1) { printf("0"); OSSemPend( sem, 0, &err ); printf("1"); OpenLED; //打开LED printf("2"); OSTimeDlyHMSM(0,0,0,100); printf("3"); OSSemPost( sem ); printf("4"); } } /********************************任务2**************************************/ static void Task2 (void *p_arg) { INT8U err; while(1) { printf("5"); OSSemPend( sem, 0, &err ); printf("6"); CloseLED; //关闭LED printf("7"); OSTimeDlyHMSM(0,0,1,0); printf("8"); OSSemPost( sem ); printf("9"); } }[/mw_shl_code]

最佳答案

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

2、UCOS在第一次初始化完成并开启以后,所有的任务就会都进入就绪态。 3、此时task1开始运行,首先输出“0”,由于sem初始为1。因此task1请求信号量成功,接着输出“1”、"2"。然后运行OSTimeDlayHMSM()函数对task1进行延时并发起任务调度,task1进入等待态,task2开始运行。 4、task2开始运行,输出"5"以后请求信号量sem,但是此时由于task1请求过一次sem了,此时sem为0,而且task2中请求sem采用的“死等”的方式,超时时间为0, ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2015-1-19 18:16:34 | 显示全部楼层
2、UCOS在第一次初始化完成并开启以后,所有的任务就会都进入就绪态。
3、此时task1开始运行,首先输出“0”,由于sem初始为1。因此task1请求信号量成功,接着输出“1”、"2"。然后运行OSTimeDlayHMSM()函数对task1进行延时并发起任务调度,task1进入等待态,task2开始运行。
4、task2开始运行,输出"5"以后请求信号量sem,但是此时由于task1请求过一次sem了,此时sem为0,而且task2中请求sem采用的“死等”的方式,超时时间为0,因此此时任务切换,切换到就绪了的最高任务,延时100ms以后,task1也就绪了,那么此时task1开始运行了。
5、task1从上次被中断的地方接着运行,输出“3”,然后OSemPost()函数运行,释放sem。函数OSSemPost()在对信号量的计数器操作之前首先检查是否还有等待该信号量的任务,如果没有的话就将信号量计数器OSEventCnt加1,如果有的话,将此任务加入就绪表中,然后调用OSSched()函数去运行等待任务中优先级别最高的任务。上面说过了task2正在傻傻的“死等"sem能够回心转意,而且此时只有task2一个在等待sem,因此sem也选择了task2的怀抱,task2重新开始运行。一切看如此的合乎情理,但是世事难料啊!task2要想和sem在一起谈何容易啊!城南小陌又逢春,只见梅花不见人!!!究其原因就是OSSchend()函数做切换的时候会首先判断当前正在运行的任务是否是最高优先级的任务,我们知道task1优先级比task2高,因此,task2暂时不能运行啊!而task1接着运行!!伤心的人儿在等待,何日再与君相见,共剪西窗烛,共话巴山夜雨!
6、task1接着运行,输出”4“、”0“。然后调用OSSemPend()函数请求信号量,但是此时sem为0,额额额?为什么sem为0?不是task1调用了一次OSSemPost()释放了sem的吗?请注意!我们前面说过,如果有任务请求sem的话,OSSemPost()函数会直接运行等待任务中优先级最高的那个,就不会将sem的计数器加1了,因此此处的sem为0!!这点很重要请注意查看OSSemPost()函数的源码!task1由于请求不到sem,不得不放弃CPU使用权,发起任务调度,此时task2才接着从在很久之前被中断的地方接着运行!
6、task2开始从上次被中断的地方接着运行,输出”6“,”7“。
7、以后发生的事情楼主自己去分析吧,我只能帮到这里了!注意一定要看OSSemPend()、OSSemPost()和OSSched()这三个函数的源码,仔细认真的分析!
开往春天的手扶拖拉机
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-1-19 22:54:48 | 显示全部楼层
1,因为任务 1的优先级高.
2,任务2既然挂起了,那就不会就绪.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

26

主题

186

帖子

0

精华

高级会员

Rank: 4

积分
810
金钱
810
注册时间
2014-5-30
在线时间
93 小时
 楼主| 发表于 2015-1-20 08:59:57 | 显示全部楼层
回复【2楼】正点原子:
-----------------------------
原子哥,关于第二个问题我还是不明白。

按照你的说法,那么可以这么推断:
上电后程序执行到任务1,把0输出挂起自己,这是任务1就到等待里去了,此时任务2执行,输出5,挂起自己。

但是实际上输出的是012···,不是05···

这个如何解释?


任务1把自己挂起时信号量是有效的,所以就应该继续执行任务1的,怎么又跑到任务2了呢?
这个执行顺序怎么和刚上电时的逻辑不一样呢?
回复

使用道具 举报

3

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
434
金钱
434
注册时间
2013-3-18
在线时间
82 小时
发表于 2015-1-20 16:38:30 | 显示全部楼层
任务2输出5之后,由于等待信号量被挂起,之后任务1输出3,然后发信号量,注意发信号亮并不是简单的+1,OSSemPost中有这几行代码
if (pevent->OSEventGrp != 0) {
        (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
        OS_EXIT_CRITICAL();
        OS_Sched();
        return (OS_ERR_NONE);
    }
此时因为任务2的优先级较1低,所以没有立即运行,而是任务1继续输出4、0然后挂起自己,任务2就运行了,输出678
回复

使用道具 举报

26

主题

186

帖子

0

精华

高级会员

Rank: 4

积分
810
金钱
810
注册时间
2014-5-30
在线时间
93 小时
 楼主| 发表于 2015-1-20 20:39:39 | 显示全部楼层
回复【4楼】holy404290384:
---------------------------------
谢谢回答,还是没有理解这里:任务1继续输出4、0然后挂起自己。挂起自己时信号量是有效的,为什么任务1没有继续执行呢???

而是去执行任务2了。


情形1:任务2输出8后发送信号量,此时任务1正在挂起,任务2发出信号量后为什么这次任务1马上就去执行了?

情形2:任务1输出3后发送一个信号量,输出4、0,然后挂起自己(其实是要等待一个信号量),但是任务1在输出3后就发送了一个信号量了,为什么此时任务1没有使用这个信号量呢? 为什么在情形1中任务2发送信号量后任务1就立马运行了(这个情况我理解:任务1的优先级高,所以抢先执行了;那为什么任务1自己发送的信号量,自己挂起时没有使用自己发送的信号量呢?这个是不是和情形2矛盾了????)。


谢谢
回复

使用道具 举报

3

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
434
金钱
434
注册时间
2013-3-18
在线时间
82 小时
发表于 2015-1-20 21:11:33 | 显示全部楼层
回复【5楼】天山狐狸:
---------------------------------
我说的还不够清楚吗?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-1-20 23:02:46 | 显示全部楼层
楼主直接单步跟踪代码去分析下吧.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

26

主题

186

帖子

0

精华

高级会员

Rank: 4

积分
810
金钱
810
注册时间
2014-5-30
在线时间
93 小时
 楼主| 发表于 2015-1-21 08:35:54 | 显示全部楼层
回复【6楼】holy404290384:
---------------------------------
不是很清楚,就那一点没有讲清楚
回复

使用道具 举报

26

主题

186

帖子

0

精华

高级会员

Rank: 4

积分
810
金钱
810
注册时间
2014-5-30
在线时间
93 小时
 楼主| 发表于 2015-1-21 08:36:07 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
好吧,我试试
回复

使用道具 举报

26

主题

186

帖子

0

精华

高级会员

Rank: 4

积分
810
金钱
810
注册时间
2014-5-30
在线时间
93 小时
 楼主| 发表于 2015-1-22 09:14:44 | 显示全部楼层
回复【10楼】zuozhongkai:
---------------------------------

谢谢ls,分析的十分清晰、幽默,语文水平很高啊。我终于明白那个地方了,原来第一次OSSemPost后sem没有加1,理解这一点所有的都理解了。再次感谢。

***************************************分割线******************************************
关于第4条我还有点疑惑,你看看我理解的对吗

你的原文如下
4、task2开始运行,输出"5"以后请求信号量sem,但是此时由于task1请求过一次sem了,此时sem为0,而且task2中请求sem采用的“死等”的方式,超时时间为0,因此此时任务切换,切换到就绪了的最高任务,延时100ms以后,task1也就绪了,那么此时task1开始运行了。

我的理解:
从“超时时间为0”  开始,我的理解是:此时任务做了切换,但切换到了空闲任务中。【在任务1调用OSTimeDlyHMSM()后就已经开始100ms计时了,并做了任务切换,即从任务1切换到了任务2。】,程序一直在空闲任务中运行,知直到100ms到了后才从空闲任务切换到了就绪到的任务1,任务1开始运行。


下面是OSTimeDly的源码,先把ticks放到OSTCBDly 中,后才做的任务切换。

void  OSTimeDly (INT32U ticks)
{
    INT8U      y;
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0u;
#endif



    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
        return;
    }
    if (OSLockNesting > 0u) {                    /* See if called with scheduler locked                */
        return;
    }
    if (ticks > 0u) {                            /* 0 means no delay!                                  */
        OS_ENTER_CRITICAL();
        y            =  OSTCBCur->OSTCBY;        /* Delay current task                                 */
        OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
        if (OSRdyTbl[y] == 0u) {
            OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
        }
        OSTCBCur->OSTCBDly = ticks;              /* Load ticks in TCB                                  */
        OS_EXIT_CRITICAL();
        OS_Sched();                              /* Find next task to run!                             */
    }
}
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2015-1-22 10:46:35 | 显示全部楼层
回复【11楼】天山狐狸:
---------------------------------
有切换到空闲任务的可能,如果task1的延时还没结束,那么肯定会切换到空闲任务的。
开往春天的手扶拖拉机
回复

使用道具 举报

26

主题

186

帖子

0

精华

高级会员

Rank: 4

积分
810
金钱
810
注册时间
2014-5-30
在线时间
93 小时
 楼主| 发表于 2015-1-22 10:53:29 | 显示全部楼层
回复【12楼】zuozhongkai:
---------------------------------
如果切换到空闲任务的话

我上面的理解对吗?
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2015-1-22 11:00:09 | 显示全部楼层
回复【13楼】天山狐狸:
---------------------------------
嗯,是的,你要知道一点的是OSSched()函数永远是在找就绪表中已经就绪了的最高优先级的那个任务运行的。此时task1的优先级最高,而且已经就绪了,那么做任务切换的时候肯定会切换到task1的
开往春天的手扶拖拉机
回复

使用道具 举报

26

主题

186

帖子

0

精华

高级会员

Rank: 4

积分
810
金钱
810
注册时间
2014-5-30
在线时间
93 小时
 楼主| 发表于 2015-1-22 11:11:50 | 显示全部楼层
回复【14楼】zuozhongkai:
---------------------------------
嗯,完全理解了

再次感谢
回复

使用道具 举报

13

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2014-10-19
在线时间
2 小时
发表于 2015-6-26 01:28:34 | 显示全部楼层
回复【10楼】zuozhongkai:
---------------------------------
楼主 假如运行任务2 是不是执行到任务2的ossempend()还要等待
回复

使用道具 举报

13

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2014-10-19
在线时间
2 小时
发表于 2015-6-26 01:29:55 | 显示全部楼层
回复【10楼】zuozhongkai:
---------------------------------
任务2等于是没有等到sem 是吧
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2015-6-26 10:06:01 | 显示全部楼层
回复【17楼】wenwu1109:
---------------------------------
运行到ossempend()函数肯定要等待指定地的信号量,如果函数超时参数设置为0就一直等待,如果不为0的话就等待指定的时间。
开往春天的手扶拖拉机
回复

使用道具 举报

1

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2013-12-12
在线时间
5 小时
发表于 2017-6-8 16:06:31 | 显示全部楼层
经典啊!
回复

使用道具 举报

10

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
187
金钱
187
注册时间
2016-8-5
在线时间
57 小时
发表于 2017-7-24 15:32:26 | 显示全部楼层
楼主你好,发送完0125 后为什么会跳到任务1去了,此时信号量计数不是0吗,不应该什么任务都不执行吗
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-23 17:17

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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