參考:
不可重入函數(shù)總結(jié)
https://blog.csdn.net/gj19890923/article/details/9017549
滿足下面條件之一的多數(shù)是不可重入函數(shù):
(1)使用了靜態(tài)數(shù)據(jù)結(jié)構(gòu)或者全局變量;
(2)調(diào)用了malloc或free;
(3)調(diào)用了標準I/O函數(shù);標準io庫很多實現(xiàn)都以不可重入的方式使用全局數(shù)據(jù)結(jié)構(gòu)。
(4)進行了浮點運算.許多的處理器/編譯器中,浮點一般都是不可重入的 (浮點運算大多使用協(xié)處理器或者軟件模擬來實現(xiàn)朝扼。
(5)調(diào)用printf。
注:printf引用全局stdout澎媒; malloc, free會引用全局的內(nèi)存分配表
在多任務(wù)環(huán)境中或者實時系統(tǒng)設(shè)計中琅绅,應(yīng)該盡可能的使用可重入函數(shù)樊诺,例如下面的函數(shù):
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;
}
該函數(shù)功能是計算不同籃子里的蘋果數(shù)仗考,函數(shù)體內(nèi)沒有訪問全局變量,不使用靜態(tài)局部變量词爬,只使用局部變量秃嗜,所以這個函數(shù)具有可重入的,如果必須使用全局變量缸夹,那么為了保證函數(shù)的安全痪寻,必須利用互斥信號量或者中斷機制來保護全局變量。例如下面函數(shù):
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操作機制就可以讓可重入函數(shù)安全的使用全局變量了芽唇,而且保證了可并行性顾画。
不可重入函數(shù),例如:
static int sum = 0;
int cout_pear(int *package,int n)
{
int i;
for(i = 0; i < n; i++)
sum += *(package ++); //(1)
return sum;
}
這個函數(shù)由于使用了靜態(tài)全局變量匆笤,對sum的并行性操作結(jié)果是未知的研侣,是不安全的操做。若此函數(shù)被多個進程調(diào)用的話炮捧,結(jié)果是未知的庶诡。因為,但語句(1)執(zhí)行完一次或者幾次后咆课,另外使用這個sum的函數(shù)可能正好被調(diào)度末誓,并得到運行機會扯俱,那么這個新運行的函數(shù)將使sum變成了另外的值,所以當(1)重新獲得運行機會時喇澡,sum的值已經(jīng)變成了另外的值迅栅,這是不可預(yù)料的結(jié)果。
也可以這樣總結(jié)晴玖,在多任務(wù)系統(tǒng)中要進行并行操作读存,應(yīng)該保證函數(shù)的可重入性(),或者使用信號量呕屎、中斷等機制來保證數(shù)據(jù)的安全性操作让簿。