可重入函數與不可重入函數

 一. 不可重入函數

  1.1. 什麼是不可重入函數

    a. 在實時系統的設計中,常常會出現多個任務調用同一個函數的狀況。若是有一個函數不幸被設計成爲不可重入這樣:那麼不一樣任務調用這個函數時可能修改其餘任務調用這個函數的數據,從而致使不可預料的後果。這樣的函數是不安全的函數,也叫不可重入函數。安全

  1.2. 不可重入函數產生

    1.2.1. 知足下列條件的函數多數是不可重入的數據結構

      a. 函數體內使用了靜態的數據結構;ide

      b. 函數體內調用了malloc()或者free()函數(malloc和free爲不可重入函數);函數

      c. 函數體內調用了標準I/O函數。設計

二. 可重入函數

  2.1. 什麼是可重入函數

    a. 可重入函數能夠被一個以上的任務調用,而沒必要擔憂數據被破壞。可重入函數任什麼時候候均可以被中斷,一段時間之後又能夠運行,而相應的數據不會丟失。可重入函數或者只使用局部變量,即保存在CPU寄存器中或堆棧中;或者使用全局變量,則要對全局變量予以保護進程

  2.2. 如何寫出可重入函數

    a. 在函數體內不訪問那些全局變量,不使用靜態局部變量,堅持只使用缺省態(auto)局部變量,寫出的函數就將是可重入的。若是必須訪問全局變量,記住利用互斥信號量來保護全局變量。或者調用該函數前關中斷,調用後再開中斷。it

三. 實例分析

   假設 Exam 是 int 型全局變量,函數 Squre_Exam 返回 Exam 平方值。那麼以下函數不具備可重入性:class

 

int Exam = 0;  
unsigned int example( int para )   
{   
    unsigned int temp;  
    Exam = para; // (**)  
    temp = Square_Exam( );  
    return temp;  
}

分析:此函數若被多個進程調用的話,其結果多是未知的,由於當(**)語句剛執行完後,另一個使用本函數的進程可能正好被激活,那麼當新激活的進程執行到此函數時,將使 Exam 賦與另外一個不一樣的 para 值,因此當控制從新回到 「temp = Square_Exam( )」 後,計算出的temp極可能不是預想中的結果。此函數應以下改進:

int Exam = 0;  
unsigned int example( int para )   
{  
    unsigned int temp;  
    [申請信號量操做] //(1)  加鎖  
    Exam = para;  
    temp = Square_Exam( );  
    [釋放信號量操做] //     解鎖   
    return temp;  
}

  申請不到「信號量」,說明另外的進程正處於給 Exam 賦值並計算其平方過程當中(即正在使用此信號),本進程必須等待其釋放信號後,纔可繼續執行。若申請到信號,則可繼續執行,但其它進程必須等待本進程釋放信號量後,才能再使用本信號。變量

相關文章
相關標籤/搜索