標(biāo)題: uC/OS-II學(xué)習(xí)筆記—任務(wù)掛起和恢復(fù) [打印本頁(yè)]

作者: xueren    時(shí)間: 2013-7-19 01:55
標(biāo)題: uC/OS-II學(xué)習(xí)筆記—任務(wù)掛起和恢復(fù)
任務(wù)在創(chuàng)建后將從睡眠態(tài)轉(zhuǎn)換到就緒態(tài),就緒的任務(wù)如果調(diào)用OSTaskSuspend將被阻塞,也就是被剝奪CPU的使用權(quán)而暫時(shí)中止運(yùn)行,轉(zhuǎn)到阻塞狀態(tài)。通過(guò)OSTaskSuspend將任務(wù)轉(zhuǎn)到阻塞態(tài)被稱為掛起任務(wù)。
被掛起的任務(wù)不能運(yùn)行,知道其他任務(wù)以該任務(wù)的優(yōu)先級(jí)作為參數(shù)調(diào)用OSTaskResume來(lái)恢復(fù)它,才能將該任務(wù)的狀態(tài)重新設(shè)置為就緒狀態(tài)。當(dāng)該任務(wù)是就緒的最高優(yōu)先級(jí)的任務(wù)時(shí),又可以得到調(diào)度而重新占領(lǐng)CPU,回到運(yùn)行態(tài)。
一個(gè)任務(wù)如果無(wú)事可做,且優(yōu)先級(jí)又較高,長(zhǎng)期占有CPU,那么其他的任務(wù)將得不到運(yùn)行而“餓死”。因此,任務(wù)在不需要運(yùn)行的時(shí)候應(yīng)該放棄CPU,掛起就是其中的一種策略,除此之外還有任務(wù)延時(shí)等策略。


由上圖可知,在運(yùn)行過(guò)程的任務(wù)因?yàn)檎{(diào)用OSTaskSuspend而被掛起到阻塞態(tài)。阻塞態(tài)的任務(wù)因?yàn)槠渌蝿?wù)以該任務(wù)的優(yōu)先級(jí)作為參數(shù)調(diào)用OSTaskResume而得到恢復(fù),恢復(fù)到就緒態(tài)。就緒的任務(wù)在優(yōu)先級(jí)變?yōu)樽罡叩那闆r下最終得到了運(yùn)行。
值得注意的是,掛起一個(gè)任務(wù)并非將其轉(zhuǎn)換掛起態(tài),而是阻塞態(tài)。任務(wù)因?yàn)橹袛嗍PU控制權(quán)才會(huì)轉(zhuǎn)換為掛起態(tài),掛起態(tài)的任務(wù)在中斷結(jié)束后直接回到運(yùn)行態(tài)。這兩者是有明顯的區(qū)別的。
函數(shù)OSTaskSuspend用來(lái)暫時(shí)停止一個(gè)任務(wù)的執(zhí)行,將任務(wù)轉(zhuǎn)換為阻塞態(tài)。如果傳遞給OSTaskSuspend的參數(shù)是OS_PRIO_SELF,則將阻塞自己,如果prio是其他任務(wù)的優(yōu)先級(jí),則將阻塞其他的就緒任務(wù)。
根據(jù)該函數(shù)執(zhí)行過(guò)程中的各種情況,返回值包括:
(^_^) OS_ERR_NONE:如果成功掛起一個(gè)任務(wù)
(^_^) OS_ERR_TASK_SUSPEND_IDLE:如果試圖阻塞空閑任務(wù)。
(^_^) OS_ERR_PRIO_INVALID:非法的優(yōu)先級(jí)
(^_^) OS_ERR_TASK_SUSPEND_PRIO:要掛起的任務(wù)不存在
(^_^) OS_ERR_TASK_NOT_EXITS:要掛起使用互斥信號(hào)量的任務(wù)。
另外有一點(diǎn)需要特別注意的是,如果掛起了一個(gè)任務(wù),那么要注意這個(gè)任務(wù)是否在等待某些事件的發(fā)生,需要防止在事件發(fā)生的時(shí)候阻塞了的任務(wù)因?yàn)槭录陌l(fā)生而運(yùn)行。
OSTaskSuspend代碼如下所示:


取消就緒表和就緒組中的就緒標(biāo)志后,被掛起的任務(wù)在將來(lái)如果沒(méi)有恢復(fù),就不能獲得CPU的使用權(quán),因此處于阻塞狀態(tài)。如果任務(wù)是自己掛起自己,實(shí)際上這時(shí)任務(wù)還是在運(yùn)行的,要等到倒數(shù)第二行代碼任務(wù)調(diào)度的時(shí)候,失去CPU。


其中OS_STAT_SUSPEND的值是0x08,即二進(jìn)制的00001000,也就是說(shuō),OSTCBStat的從低到高的第4位標(biāo)志著任務(wù)是否被掛起。
換句話說(shuō),當(dāng)OSTCBStat的第4位是1時(shí),標(biāo)志著任務(wù)被掛起,否則任務(wù)沒(méi)有被使用OSTaskSuspend掛起到阻塞態(tài)。
函數(shù)OSTaskSuspend用來(lái)暫時(shí)停止一個(gè)任務(wù)的執(zhí)行,將任務(wù)狀態(tài)轉(zhuǎn)換為阻塞態(tài)。那么處于阻塞態(tài)的任務(wù)要想得到運(yùn)行,必須先恢復(fù)到就緒態(tài)。這個(gè)恢復(fù)被掛起的任務(wù)的函數(shù)就是OSTaskResume,它和OSTaskSuspend正好是一對(duì)函數(shù)。
在OSTaskSuspend掛起一個(gè)任務(wù)的時(shí)候,要修改就緒表和就緒組,取消任務(wù)的就緒標(biāo)志;那么恢復(fù)一個(gè)任務(wù)的時(shí)候,應(yīng)該加上就緒標(biāo)志。另外,對(duì)于掛起的標(biāo)志,是在任務(wù)控制塊中的OSTCBStat從低到高的第4位,因此,如果恢復(fù)一個(gè)任務(wù),應(yīng)該看這一位是否已經(jīng)被置位,如果沒(méi)有被置位,那么恢復(fù)操作也應(yīng)該是無(wú)效的。最后,如果一切正常,再將該位進(jìn)行復(fù)位。
OSTaskResume代碼如下所示:




if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY)  判斷要恢復(fù)的任務(wù)是否為被OSTaskSuspend掛起。當(dāng)然,如果對(duì)應(yīng)優(yōu)先級(jí)的任務(wù)并沒(méi)有被OSTaskSuspend掛起,就談不上使用OSTaskResume恢復(fù)。將要恢復(fù)的任務(wù)稱為目標(biāo)任務(wù),目標(biāo)任務(wù)的控制塊稱為目標(biāo)TCB,那么,前面將目標(biāo)任務(wù)的TCB的地址已經(jīng)賦給了ptcb,目標(biāo)TCB的OSTCBStat從低到高的第4位標(biāo)志著任務(wù)是否被掛起。而宏OS_STAT_SUSPEND就是二進(jìn)制的00001000,因此ptcb->OSTCBStat&OS_STAT_SUSPEND剛好是屏蔽了OSTCBStat中的所有其他的位,因?yàn)?amp;是按位與,只留下了第4位。OS_STAT_RDY的值是0,所以ptcb->OSTCBStat&OS_STAT_SUSPEND的結(jié)果不等于0就說(shuō)明了確實(shí)是被OSTaskSuspend掛起的任務(wù)。





歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1