標籤:
本文轉載自:http://www.cnblogs.com/parrynee/archive/2010/01/29/1659071.html
可重新進入函數
在 即時系統的設計中,經常會出現多個任務調用同一個函數的情況。如果這個函數不幸被設計成為不可重新進入的函數的話,那麼不同任務調用這個函數時可能修改其他任 務調用這個函數的資料,從而導致不可預料的後果。那麼什麼是可重新進入函數呢?所謂可重新進入是指一個可以被多個任務調用的過程,任務在調用時不必擔心資料是否會 出錯。不可重新進入函數在即時系統設計中被視為不安全函數。
滿足下列條件的函數多數是不可重新進入的:
(1)函數體內使用了靜態資料結構;
(2)函數體內調用了malloc()或者free()函數;
(3)函數體內調用了標準I/O函數。
如何寫出可重新進入的函數?在函數體內不訪問那些全域變數,不使用靜態局部變數,堅持只使用預設態(auto)局部變數,寫出的函數就將是可重新進入的。如果必須訪問全域變數,記住利用互斥訊號量來保護全域變數。或者調用該函數前關中斷,調用後再開中斷。
可重新進入函數可以被一個以上的任務調用,而不必擔心資料被破壞。可重新進入函數任何時候都可以被中斷,一段時間以後又可以運行,而相應的資料不會丟失。可重新進入函數或者只使用局部變數,即儲存在CPU寄存器中或堆棧中;或者使用全域變數,則要對全域變數予以保護。
說法2:
一個可重新進入的函數簡單來說,就是:可以被中斷的函數。就是說,你可以在這個函數執行的任何時候中斷他的運行,在任務調度下去執行另外一段代 碼而不會出現什麼錯誤。而不可重新進入的函數由於使用了一些系統資源,比如全域變數區,中斷向量表等等,所以他如果被中斷的話,可能出現問題,所以這類函數是 不能運行在多任務環境下的。
基本上下面的函數是不可重新進入的
(1)函數體內使用了靜態資料結構;
(2)函數體內調用了malloc()或者free()函數;
(3)函數體內調用了標準I/O函數。
把一個不可重新進入函數變成可重新進入的唯一方法是用可重新進入規則來重寫他。
其實很簡單,只要遵守了幾條很容易理解的規則,那麼寫出來的函數就是可重新進入的。
第一,不要使用全域變數。因為別的代碼很可能覆蓋這些變數值。
第二,在和硬體發生互動的時候,切記執行類似disinterrupt()之類的操作,就是關閉硬體中斷。完成互動記得開啟中斷,在有些系列上,這叫做“進入/退出核心”或者用OS_ENTER_KERNAL/OS_EXIT_KERNAL來描述。//這是臨界區保護
第三,不能調用任何不可重新進入的函數。
第四,謹慎使用堆棧。最好先在使用前先OS_ENTER_KERNAL。
還有一些規則,都是很好理解的,總之,時刻記住一句話:保證中斷是安全的!
可重新進入函數與不可重新進入函數【轉】