天天看點

什麼是可重入函數和不可重入函數

可重入函數

     在 實時系統的設計中,經常會出現多個任務調用同一個函數的情況。如果這個函數不幸被設計成為不可重入的函數的話,那麼不同任務調用這個函數時可能修改其他任 務調用這個函數的資料,進而導緻不可預料的後果。那麼什麼是可重入函數呢?所謂可重入是指一個可以被多個任務調用的過程,任務在調用時不必擔心資料是否會 出錯。不可重入函數在實時系統設計中被視為不安全函數。

     滿足下列條件的函數多數是不可重入的:

(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。

還有一些規則,都是很好了解的,總之,時刻記住一句話:保證中斷是安全的!

繼續閱讀