轉載自:http://blog.chinaunix.net/uid-20621895-id-196621.html
可重入函數可以做這樣的基本定義:重入意味着這個函數可以重復進入,可以被並行調用,可以被中斷,它只使用自身棧上的數據變量,它不依賴於任務環境,在多任務調度過程中,它是安全的,不必擔心數據出錯。
不可重入函數基本上與可重入函數有相反的定義了:不可重入,意味着不可被並行調度,否則會產生不可預料的結果,這些函數提內一般使用了靜態(static)的數據結構,使用了malloc()或者free()函數,使用了標准I/O函數等等。
在多任務環境中或者實時系統設計中,應該盡可能的使用可重入函數,例如下面的函數:
int count_apple(int *package,int n)
{
int temp = 0;
int i;
if(package == NULL)
exit(1);
for(i = 0;i < n; i++)
temp += *(package++);
return temp;
}
{
int temp = 0;
int i;
if(package == NULL)
exit(1);
for(i = 0;i < n; i++)
temp += *(package++);
return temp;
}
該函數功能是計算不同籃子里的蘋果數,函數體內沒有訪問全局變量,不使用靜態局部變量,只使用局部變量,所以這個函數具有可重入的,如果必須使用全局變量,那么為了保證函數的安全,必須利用互斥信號量或者中斷機制來保護全局變量。例如下面函數:
int *package;
int count_apple(int n)
{
int temp = 0;
int i;
P操作(申請信號量);
if(package == NULL)
{
V操作(釋放信號量);
exit(1)
}
for(i = 0; i < n; i++)
temp += *(package++);
V操作(釋放信號量);
return temp;
}
象上面的PV操作機制就可以讓可重入函數安全的使用全局變量了,而且保證了可並行性。
不可重入函數,例如:
static int sum = 0;
int cout_pear(int *package,int n)
{
int i;
for(i = 0; i < n; i++)
sum += *(package ++); //(1)
return sum;
}
這個函數由於使用了靜態全局變量,對sum的並行性操作結果是未知的,是不安全的操做。若此函數被多個進程調用的話,結果是未知的。因為,但語句(1)執行完一次或者幾次后,另外使用這個sum的函數可能正好被調度,並得到運行機會,那么這個新運行的函數將使sum變成了另外的值,所以當(1)重新獲得運行機會時,sum的值已經變成了另外的值,這是不可預料的結果。
也可以這樣總結,在任務系統中要進行並行操作,應該保證函數的可重入性,或者使用信號量、中斷等機制來保證數據的安全性操作。