4 回答

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

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