天天看點

函數可重入的概念

可重入的概念 

          主要用于多任務環境中,一個可重入的函數簡單來說就是可以被中斷的函數,也就是說,可以在這個函數執行的任何時刻中斷它,轉入OS排程下去執行另外一段代碼,而傳回控制時不會出現什麼錯誤;而不可重入的函數由于使用了一些系統資源,比如全局變量區,中斷向量表等,是以它如果被中斷的話,可能會出現問題,這類函數是不能運作在多任務環境下的。          也可以這樣了解,重入即表示重複進入,首先它意味着這個函數可以被中斷,其次意味着它除了使用自己棧上的變量以外不依賴于任何環境(包括static),這樣的函數就是purecode(純代碼)可重入,可以允許有該函數的多個副本在運作,由于它們使用的是分離的棧,是以不會互相幹擾。如果确實需要通路全局變量(包括static),一定要注意實施互斥手段。可重入函數在并行運作環境中非常重要,但是一般要為通路全局變量付出一些性能代價。     編寫可重入函數時,若使用全局變量,則應通過關中斷、信号量(即P、V操作)等手段對其加以保護。     說明:若對所使用的全局變量不加以保護,則此函數就不具有可重入性,即當多個程序調用此函數時,很有可能使有關全局變量變為不可知狀态。

       示例:假設Exam是int型全局變量,函數Squre_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;         }     (1)若申請不到“信号量”,說明另外的程序正處于給Exam指派并計算其平方過程中(即正在使用此信号),本程序必須等待其釋放信号後,才可繼續執行。若申請到信号,則可繼續執行,但其它程序必須等待本程序釋放信号量後,才能再使用本信号。

保證函數的可重入性的方法:     在寫函數時候盡量使用局部變量(例如寄存器、堆棧中的變量),對于要使用的全局變量要加以保護(如采取關中斷、信号量等方法),這樣構成的函數就一定是一個可重入的函數。

     在實時系統的設計中,經常會出現多個任務調用同一個函數的情況。如果這個函數不幸被設計成為不可重入的函數的話,那麼不同任務調用這個函數時可能修改其他任務調用這個函數的資料,進而導緻不可預料的後果。那麼什麼是可重入函數呢?所謂可重入函數是指一個可以被多個任務調用的過程,任務在調用時不必擔心資料是否會出錯。不可重入函數在實時系統設計中被視為不安全函數。滿足下列條件的函數多數是不可重入的:     1) 函數體内使用了靜态的資料結構;     2) 函數體内調用了malloc()或者free()函數;     3) 函數體内調用了标準I/O函數。

    問題1,如何編寫可重入的函數?     答:在函數體内不通路那些全局變量,不使用靜态局部變量,堅持隻使用局部變量,寫出的函數就将是可重入的。如果必須通路全局變量,記住利用互斥信号量來保護全局變量。

    問題2,如何将一個不可重入的函數改寫成可重入的函數?     答:把一個不可重入函數變成可重入的唯一方法是用可重入規則來重寫它。其實很簡單,隻要遵守了幾條很容易了解的規則,那麼寫出來的函數就是可重入的。     1) 不要使用全局變量。因為别的代碼很可能覆寫這些變量值。     2) 在和硬體發生互動的時候,切記執行類似disinterrupt()之類的操作,就是關閉硬體中斷。完成互動記得打開中斷,在有些系列上,這叫做“進入/退出核心”。     3) 不能調用其它任何不可重入的函數。     4) 謹慎使用堆棧。最好先在使用前先OS_ENTER_KERNAL。

    堆棧操作涉及記憶體配置設定,稍不留神就會造成益出導緻覆寫其他任務的資料,是以,請謹慎使用堆棧!最好别用!很多黑客程式就利用了這一點以便系統執行非法代碼進而輕松獲得系統控制權。還有一些規則,總之,時刻記住一句話:保證中斷是安全的!

繼續閱讀