引用: 原帖由 花开花谢 于 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的空闲任务。