[uCOS/uCGUI] UCOS2的互斥型信号量的问题

lr2131   2012-12-19 09:39 楼主
请教一下分析了源码的朋友两个问题:
1.UCOS2的互斥型信号量的API能不能用于多个任务中,而不只是两个任务中。或者说互斥锁能不能用于两个任务以上的互斥。

2.如果可以用于多个任务中。那假如说当前有一个任务持有互斥锁,其他任务调用OSMutexPend()时,就会挂起同时会把相关信息加到这个互斥锁对应的挂起队列中。那么持有互斥锁的任务在调用OSMutexPost()的时候,是应该从这个挂起队列里面中抽取优先级最高的置为就绪态,还是把队列中的全部任务全部置为就绪。换个说法就是全部唤醒还是只唤醒优先级最高的那个。

回复评论 (12)

第一个问题:互斥型信号量是可以用于多任务中的。
第二个问题:寻找最高优先级的任务,不会对所有任务使其就绪。
点赞  2012-12-19 22:29
第二个问题,为什么不是让全部等待任务就绪,而是从等待队列中选取最高优先级的任务就绪呢。
点赞  2012-12-20 08:24
互斥信号量的作用就是资源分配,就绪等价于就是获得了资源!资源只有1个。
点赞  2012-12-20 13:21
引用: 原帖由 花开花谢 于 2012-12-20 13:21 发表
互斥信号量的作用就是资源分配,就绪等价于就是获得了资源!资源只有1个。
就绪是就绪,不是获得资源的意思。任务或者说是线程的状态,一般有运行态,就绪态,挂起态。运行态就是在运行中的状态,就绪就是等待调度器调度它,挂起态是由于某个条件不满足而被挂起,满足了后会先进入就绪态,然后才可能进入运行态,所以你的说法是不对的,概念没有搞清楚。另外,获得了资源或者说是获得锁,也不意味着它一定在运行态或就绪态,他也可以调用系统延时sleep()来挂起自己,当然在临界区这样的写法是不好的,一般不会在临界区占用太长时间。
点赞  2012-12-20 13:28

回复 5楼 lr2131 的帖子

你在字词概念里局限了。那,按你“锁钥”的理念做比喻,需要锁钥的任务在按优先级排队,运行中的任务把锁钥放回,你说谁拿到?
点赞  2012-12-20 15:31
引用: 原帖由 花开花谢 于 2012-12-20 15:31 发表
你在字词概念里局限了。那,按你“锁钥”的理念做比喻,需要锁钥的任务在按优先级排队,运行中的任务把锁钥放回,你说谁拿到?
首先持有互斥锁的任务在调用post时确实会从该互斥锁对应的任务等待队列中找出最高优先级的任务,置为就绪态,但不一定它马上就会拿到互斥锁,因为在post之后,调度器会从就绪队列中取出所有就绪任务中最高优先级的任务。那这里要分2种情况了:

因为UCOS2是不支持同级优先级的任务调度的,所以这个刚调用了post的任务,假如就叫做任务A吧,而置为就绪态的那个任务就说是B吧。这里不考虑优先级反转的问题,和这是两回事。所以,要么A比B优先级高,要么B比A高,只有这两种情况,因为A不可能和B的优先级相同。

第一种情况,B比A高,现在A也处于就绪态,B也是,B比A优先级高,自然就要做一次调度,将调度B任务,B任务又由就绪态进入运行态,同时马上获得锁(如果不来中断)。那么就出现了你说的情况。

再考虑第二种情况,A比B高。虽然置B为就绪态,但A还是就绪态,A比B高,所以调度器不会调度B进入运行态,B还是在就绪态,Post正常返回,A还是回到运行态,而目前没有任何一个任务持有该互斥锁,当然A会不会再pend成功该锁,就看后面的代码怎么写,如果是调用了任务级调度的API,例如Sleep,A进入挂起状态,将引发一次调度,那么B有机会被调度从而获得锁。这两种结果是不同的,就因为UCOS2是基于优先级调度的,总是选取就绪队列中最高优先级的任务运行。

不要搞错了就绪和运行。运行态的任务数总是小于或等于CPU内核的数量的,当在调度器下时,没有用户任务处于运行态。而就绪态的任务至少是一个,而那至少的一个是OS的空闲任务,它永远处于就绪态,以避免所有的用户任务都挂起了而调度器没有任务可调度了,但它的优先级最低。而且它里面不能用到任务级调度的API,例如sleep。你能看到UCOS2下有个IDEL任务吧,其实你要是打开windows任务管理器,还能看到进程栏中有“System Idle Process”,这就是Windows的空闲任务。
  • 2121.bmp
点赞  2012-12-20 16:27

回复 5楼 lr2131 的帖子

这个,我也赞同,就绪不是获得资源,我在回答你问题时,措辞不好。
对第二个问题:很多任务都在相应事件块得就绪表内,本身都处于就绪状态,调用OSMutexPost()的时候
从就绪的任务中,挑选最高优先级的任务执行。
点赞  2012-12-20 16:43
引用: 原帖由 liuyuansuccess 于 2012-12-20 16:43 发表
这个,我也赞同,就绪不是获得资源,我在回答你问题时,措辞不好。
对第二个问题:很多任务都在相应事件块得就绪表内,本身都处于就绪状态,调用OSMutexPost()的时候
从就绪的任务中,挑选最高优先级的任务执行。
第二个不对,上面那个不是说了吗,还要看这个挑出来的最高优先级任务和调用OSMutexPost的任务的优先级,哪个高哪个低,才能决定,不一定总会调度那个挑出来的最高优先级的任务。
点赞  2012-12-20 17:03
任务要想获得互斥锁,必须在运行态下,不能进入运行态就不能获得互斥锁。而在进入运行态之前自然必须是就绪态。
点赞  2012-12-20 17:08
嗯,我明白分歧点在哪,第二种情况:
你可能认为OSMutexPost()没有将mutex给任务B,但你赞同B进入了就绪态,

于是,你想想?矛盾了吧。
点赞  2012-12-20 17:25
引用: 原帖由 花开花谢 于 2012-12-20 17:25 发表
嗯,我明白分歧点在哪,第二种情况:
你可能认为OSMutexPost()没有将mutex给任务B,但你赞同B进入了就绪态,

于是,你想想?矛盾了吧。
我是赞同B进入了就绪态,但OSMutexPost是不会把互斥锁直接交给B的(可能有的OS会这么做,毕竟我也没有接触过其他的OS,但UCOS2好像是不会直接把锁交给B的),所以需要他自己进入了运行态下,如果A没有再去pend锁,然后B马上会在Pend的循环中才会真正的获得互斥锁。这个理解并不矛盾呀。
点赞  2012-12-20 17:39
引用: 原帖由 花开花谢 于 2012-12-20 17:25 发表
嗯,我明白分歧点在哪,第二种情况:
你可能认为OSMutexPost()没有将mutex给任务B,但你赞同B进入了就绪态,

于是,你想想?矛盾了吧。
真不好意思,回去在板子上用UCOS2做了下试验,发现我的理解确实是错的。

UCOS2按优先级调度的理解这个是没错。调用post时,确实是把等待队列中最高优先级的任务置为就绪,但同时也把mutex分给了它(这就是我理解有误的地方,我以为没有这一步),至于会不会调度它运行,就看它的优先级有没有调用post的任务的优先级高了(这个理解是对的)。

不管怎么样,不希望我的错误理解误导了别人。谨以此贴,修正之前的错误。
点赞  2012-12-25 10:11
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复