4 回答

TA貢獻(xiàn)2016條經(jīng)驗(yàn) 獲得超9個(gè)贊
任務(wù)棧和函數(shù)棧有很大不同,要回答你的問題首先應(yīng)該需要知道任務(wù)是怎樣切換的以及切換過程對(duì)棧的操作。
正如你所說,每個(gè)任務(wù)都需要分配一個(gè)內(nèi)存空間,這個(gè)內(nèi)存空間作為任務(wù)棧,在任務(wù)運(yùn)行時(shí)使用。先說單任務(wù)情況,給該任務(wù)分配一個(gè)內(nèi)存空間作為任務(wù)棧,假設(shè)在一個(gè)時(shí)候程序暫停,再運(yùn)行任務(wù)時(shí),仍然可以接著剛才停之前運(yùn)行處繼續(xù)執(zhí)行,為啥呢?因?yàn)樵谕5臅r(shí)候該任務(wù)棧保存了所有該任務(wù)的信息,再回來時(shí)可以繼續(xù)執(zhí)行。
換到多任務(wù),每次執(zhí)行代碼cpu是不會(huì)關(guān)心是什么任務(wù),它只會(huì)根據(jù)當(dāng)前指令和棧里的信息執(zhí)行而已。試想一下,一個(gè)任務(wù)執(zhí)行的時(shí)候被打斷,再次返回時(shí)棧里的信息不變,它是不是可以按照被打斷前那樣繼續(xù)執(zhí)行。
好了,接下來該說切換任務(wù)時(shí)怎么找到棧。要切換任務(wù)一般在中斷或者陷阱產(chǎn)生后才切換,也就是說當(dāng)前任務(wù)將被打斷,進(jìn)去中斷后操作系統(tǒng)(ucos2等)需要將一些必要的寄存器信息保存到該任務(wù)棧中,然后找到即將運(yùn)行的任務(wù)棧,恢復(fù)寄存器信息即可運(yùn)行別的任務(wù)。舉個(gè)例子,假設(shè)任務(wù)a在地址為0x0a0000的指令處被打斷,此時(shí)pc寄存器(假設(shè)該寄存器存放當(dāng)前指令地址的寄存器)和其他一些相關(guān)寄存器被保存到該任務(wù)的任務(wù)棧中。需要切回該任務(wù)時(shí),只要從該任務(wù)棧中恢復(fù)這些寄存器即可,此時(shí)cpu就知道任務(wù)剛才被打斷時(shí)在地址為0x0a0000處,就可以沿著該地址繼續(xù)執(zhí)行。
任務(wù)切換時(shí)cpu入棧出棧確實(shí)不用普通用戶關(guān)系,不關(guān)心并不是什么都沒做,這部分已經(jīng)由操作系統(tǒng)處理(如果你需要移植的話,怎么出棧怎么入棧可以自己寫),出棧入棧按照一定的順序保障寄存器恢復(fù)正確。

TA貢獻(xiàn)1821條經(jīng)驗(yàn) 獲得超6個(gè)贊
每個(gè)任務(wù)都有自己的堆??臻g。堆棧必須聲明為OS_STK類型,并且由連續(xù)的內(nèi)存空間組成。用戶可以靜態(tài)分配堆??臻g(在編譯的時(shí)候分配)也可以動(dòng)態(tài)地分配堆棧空間(在運(yùn)行的時(shí)候分配)。靜態(tài)堆棧聲明如程序清單 L4.4和4.5所示,這兩種聲明應(yīng)放置在函數(shù)的外面。
程序清單 L4.4 靜態(tài)堆棧
static OS_STK MyTaskStack[stack_size];
或 OS_STK MyTaskStack[stack_size];
用戶可以用C編譯器提供的malloc()函數(shù)來動(dòng)態(tài)地分配堆??臻g,如程序清單 L4.6所示。在動(dòng)態(tài)分配中,用戶要時(shí)刻注意內(nèi)存碎片問題。特別是當(dāng)用戶反復(fù)地建立和刪除任務(wù)時(shí),內(nèi)存堆中可能會(huì)出現(xiàn)大量的內(nèi)存碎片,導(dǎo)致沒有足夠大的一塊連續(xù)內(nèi)存區(qū)域可用作任務(wù)堆棧,這時(shí)malloc()便無法成功地為任務(wù)分配堆??臻g。
程序清單 L L4.6 用malloc()為任務(wù)分配堆??臻g
OS_STK *pstk;
pstk = (OS_STK *)malloc(stack_size);
If (pstk != (OS_STK *)0) { /* 確認(rèn)malloc()能得到足夠地內(nèi)存空間 */
Create the task;
}
添加回答
舉報(bào)