-
可重入函數
鎖定
- 中文名
- 可重入函數
- 外文名
- Reentrant Function
- 用 於
- 多任務環境
- 釋 義
- 可以被中斷的函數
- 相 關
- 不可重入函數
可重入函數簡介
可重入函數也可以這樣理解,重入即表示重複進入,首先它意味着這個函數可以被中斷,其次意味着它除了使用自己棧上的變量以外不依賴於任何環境(包括static),這樣的函數就是purecode(純代碼)可重入,可以允許有多個該函數的副本在運行,由於它們使用的是分離的棧,所以不會互相干擾。如果確實需要訪問全局變量(包括static),一定要注意實施互斥手段。可重入函數在並行運行環境中非常重要,但是一般要為訪問全局變量付出一些性能代價。
[1]
可重入函數注意事項
可重入函數示例
假設Exam是int型全局變量,函數Square_Exam返回Exam平方值。那麼如下函數不具有可重入性。
unsigned int example(int para) { unsigned int temp; Exam = para; // (**) temp = Square_Exam(); return temp; }
此函數若被多個進程調用的話,其結果可能是未知的,因為當(**)語句剛執行完後,另外一個使用本函數的進程可能正好被激活,那麼當新激活的進程執行到此函數時,將使Exam賦予另一個不同的para值,所以當控制重新回到“temp = Square_Exam( )”後,計算出的temp很可能不是預想中的結果。此函數應如下改進。
unsigned int example( int para ) { unsigned int temp; [申請信號量操作] //(1) Exam = para; temp = Square_Exam( ); [釋放信號量操作] return temp; }
若申請不到“信號量”,説明另外的進程正處於給Exam賦值並計算其平方過程中(即正在使用此信號),本進程必須等待其釋放信號後,才可繼續執行。若申請到信號,則可繼續執行,但其它進程必須等待本進程釋放信號量後,才能再使用本信號。
VxWorks中採取的可重入的技術有:
* 動態堆棧變量(各子函數有自己獨立的堆棧空間)
* 受保護的全局變量和靜態變量
可重入函數與線程安全的關係
可重入與線程安全兩個概念都關係到函數處理資源的方式。但是,他們有重大區別:
- 可重入概念會影響函數的外部接口,而線程安全只關心函數的實現。
- 大多數情況下,要將不可重入函數改為可重入的,需要修改函數接口,使得所有的數據都通過函數的調用者提供。
- 要將非線程安全的函數改為線程安全的,則只需要修改函數的實現部分。一般通過加入同步機制以保護共享的資源,使之不會被幾個線程同時訪問。
- 操作系統背景與CPU調度策略:
- 可重入是在單線程操作系統背景下,重入的函數或者子程序,按照後進先出的線性序依次執行完畢。
- 多線程執行的函數或子程序,各個線程的執行時機是由操作系統調度,不可預期的,但是該函數的每個執行線程都會不時的獲得CPU的時間片,不斷向前推進執行進度。
- 可重入函數未必是線程安全的;線程安全函數未必是可重入的。
- 例如,一個函數打開某個文件並讀入數據。這個函數是可重入的,因為它的多個實例同時執行不會造成衝突;但它不是線程安全的,因為在它讀入文件時可能有別的線程正在修改該文件,為了線程安全必須對文件加“同步鎖”。
可重入函數不可重入
在實時系統的設計中,經常會出現多個任務調用同一個函數的情況。如果這個函數被設計成為不可重入的函數的話,那麼不同任務調用這個函數時可能修改其他任務用到的數據,從而導致不可預料的後果。那麼什麼是可重入函數呢?所謂可重入函數是指一個可以被多個任務調用的函數(過程),任務在調用時不必擔心數據是否會出錯。不可重入函數在實時系統設計中被視為不安全函數。
[1]
滿足下列條件的函數多數是不可重入的:
1) 函數體內使用了靜態的數據結構;
2) 函數體內調用了malloc()或者free()函數;
3) 函數體內調用了標準I/O函數。
下面舉例加以説明。
A. 可重入函數
void strcpy(char *lpszDest, char *lpszSrc) { while(*lpszDest++=*lpszSrc++); *dest=0; }
B. 不可重入函數1
char cTemp;//全局變量 void SwapChar1(char *lpcX, char *lpcY) { cTemp=*lpcX; *lpcX=*lpcY; lpcY=cTemp;//訪問了全局變量 }
C. 不可重入函數2
void SwapChar2(char *lpcX,char *lpcY) { static char cTemp;//靜態局部變量 cTemp=*lpcX; *lpcX=*lpcY; lpcY=cTemp;//使用了靜態局部變量 }
- 詞條統計
-
- 瀏覽次數:次
- 編輯次數:22次歷史版本
- 最近更新: 志龙的小胜利