可重入函數

可重入與不可重入
2007年08月26日 星期日 15:20
一:可重入函數
     
 

在實時系統的設計中,經常會出現多個任務調用同一個函數的情況。如果這個函數不幸被設計成爲不可重入的函數的話,那麼不同任務調用這個函數時可能修改其他任務調用這個函數的數據,從而導致不可預料的後果。那麼什麼是可重入函數呢?

       所謂可重入函數是指一個可以被多個任務調用的過程,任務在調用時不必擔心數據是否會出錯。不可重入函數在實時系統設計中被視爲不安全函數。

       滿足下列條件的函數多數是不可重入的:
(1)函數體內使用了靜態的數據結構;
(2)函數體內調用了malloc()或者free()函數;
(3)函數體內調用了標準I/O函數。

       下面舉例加以說明。

可重入函數
void strcpy(char* lpszDest, char* lpszSrc)
{
       while(*lpszDest++ = *lpszSrc++);
       *dest=0;
}

非可重入函數1
char cTemp;              // 全局變量

void SwapChar1(char* lpcX, char* lpcY)
{
       cTemp = *lpcX;
       *lpcX = *lpcY;
       lpcY = cTemp;       // 訪問了全局變量,在分享內存的多個線程中可能造成問題
}

非可重入函數2
void SwapChar2(char* lpcX, char* lpcY)
{
       static char cTemp;    // 靜態局部變量
       cTemp = *lpcX;
       *lpcX = *lpcY;

       lpcY = cTemp;   
// 使用了靜態局部變量,在分享內存的多個線程中可能造成問題
}

       如何寫出可重入的函數?在函數體內不訪問那些全局變量,不使用靜態局部變量,堅持只使用局部變量,寫出的函數就將是可重入的。如果必須訪問全局變量,記住利用互斥信號量來保護全局變量。:)

二: 一、可重入函數  
1)什麼是可重入性?  
可重入(reentrant)函數可以由多於一個任務併發使用,而不必擔心數據錯誤。相反, 不可重入(non-reentrant)函數不能由超過一個任務所共享,除非能確保函數的互斥(或者使用信號量,或者在代碼的關鍵部分禁用中斷)。可重入函數可以在任意時刻被中斷,稍後再繼續運行,不會丟失數據。可重入函數要麼使用本地變量,要麼在使用全局變量時保護自己的數據。  

2)可重入函數:  
不爲連續的調用持有靜態數據。  
不返回指向靜態數據的指針;所有數據都由函數的調用者提供。  
使用本地數據,或者通過製作全局數據的本地拷貝來保護全局數據。  
如果必須訪問全局變量,記住利用互斥信號量來保護全局變量。  
絕不調用任何不可重入函數。  

3)不可重入函數:  
函數中使用了靜態變量,無論是全局靜態變量還是局部靜態變量。  
函數返回靜態變量。  
函數中調用了不可重入函數。  
函數體內使用了靜態的數據結構;  
函數體內調用了malloc()或者free()函數;  
函數體內調用了其他標準I/O函數。  
函數是singleton中的成員函數而且使用了不使用線程獨立存儲的成員變量 。  
總的來說,如果一個函數在重入條件下使用了未受保護的共享的資源,那麼它是不可重入的。

發佈了1 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章