可重入函數與不可重入函數的區別


轉載自: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 *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的值已經變成了另外的值,這是不可預料的結果。
   也可以這樣總結,在任務系統中要進行並行操作,應該保證函數的可重入性,或者使用信號量、中斷等機制來保證數據的安全性操作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM