可重入型函數可以被一個以上的任務調用,而不必擔心數據的破壞。可重入型函數任何時候都可以被中斷,一段時間以後又可以運行,而相應數據不會丟失。可重入型函數或者只使用局部變量,即變量保存在CPU寄存器中或堆棧中。如果使用全局變量,則要對全局變量予以保護。如下程序是一個可重入型函數的例子。
void strcpy(char *dest, char *src) { while (*dest++ = *src++) { ; } *dest = NUL; }
函數Strcpy()做字符串復制。因為參數是存在堆棧中的,故函數Strcpy()可以被多個任務調用,而不必擔心各任務調用函數期間會互相破壞對方的指針。
不可重入型函數的例子如下程序所示。Swap()是一個簡單函數,它使函數的兩個形式變量的值互換。為便於討論,假定使用的是可剝奪型內核,中斷是開著的,Temp定義為整數全程變量。
int Temp; void swap(int *x, int *y) { Temp = *x; *x = *y; *y = Temp; }
程序員打算讓Swap() 函數可以為任何任務所調用,如果一個低優先級的任務正在執行Swap()函數,而此時中斷發生了,於是可能發生的事情如下圖所示。表示中斷發生時Temp已被賦值1,中斷服務子程序使更優先級的任務就緒,當中斷完成時,內核(假定使用的是μC/OS-Ⅱ)使高優先級的那個任務得以運行,高優先級的任務調用Swap()函數是Temp賦值為3。這對該任務本身來說,實現兩個變量的交換是沒有問題的,交換後Z的值是4,X的值是3。然後高優先級的任務通過調用內核服務函數中的延遲一個時鐘節拍,釋放了CPU的使用權,低優先級任務得以繼續運行.注意,此時Temp的值仍為3!在低優先級任務接著運行時,Y的值被錯誤地賦為3,而不是正確值1。
請注意,這只是一個簡單的例子,如何能使代碼具有可重入性一看就明白。然而有些情況下,問題並非那麼易解。應用程序中的不可重入函數引起的錯誤很可能在測試時發現不了,直到產品到了現場問題才出現。如果在多任務上您還是把新手,使用不可重入型函數時,千萬要當心。
使用以下技術之一即可使Swap()函數具有可重入性:
1. 把Temp定義為局部變量
2. 調用Swap()函數之前關中斷,調動後再開中斷
3. 用信號量禁止該函數在使用過程中被再次調用
如果中斷發生在Swap()函數調用之前或調用之後,兩個任務中的X,Y值都會是正確的。