1. 程式人生 > >函式的可重入性理解

函式的可重入性理解

  最近,專案要求可能需要做博通的交換晶片的驅動程式,涉及到多使用者同時進行操作,和大量的資料處理,因此在進行程式碼架構的時候需要進行前期簡單的驗證設計。考慮到一點就是程式設計的可重入性。經過簡單的搜尋,在維基百科和其他朋友的帖子裡找到了相關概念。為了幫助自己今後理解,特地將此概念加上自己的理解整理在此。

一、維基百科解釋

複製程式碼
 1 若一個程式或子程式可以安全的被並行執行,則稱其為可重入(reentrant或re-entrant)的;即當該子程式正在執行時,可以再次  
 2 進入並執行它。若一個函式是可重入的,則該函式必須滿足一下必要條件:  
 3  1、不能含有靜態(全域性)非常量資料。    
4 5 2、不能返回靜態(全域性)非常量資料的地址。 6 7 3、只能處理由呼叫者提供的資料。 8 作為可重入函式的輸入引數,只能由呼叫者提供,而且所提供的輸入資料必須滿足上面兩點要求 9 10 4、不能依賴於單例項模式資源的鎖。 11 12 5、不能呼叫不可重入的函式。 13 <函式內部,儘量不能用 malloc 和 free 之類的方法進行記憶體分配和釋放,如果使用,一般情況下會造成該函式的不可重入>
複製程式碼

二、百度百科解釋

複製程式碼
1 可重入函式主要用於多工環境中。
2 一個可重入的函式簡單來說就是可以被中斷的函式,也就是說,可以在這個函式執行的任何時刻中斷它,轉入OS排程下去執行另外一段程式碼,而返回控制時不會出現什麼錯誤。
3 不可重入的函式由於使用了一些系統資源,比如全域性變數區,中斷向量表等,所以它如果被中斷的話,可能會出現問題,這類函式是不能執行在多工環境下的。 4 可重入函式也可以這樣理解,重入即表示重複進入,首先它意味著這個函式可以被中斷,其次意味著它除了使用自己棧上的變數以外不依賴於任何環境(包括 static),這樣的函式就是purecode(純程式碼)可重入,可以允許有該函式的多個副本在執行,由於它們使用的是分離的棧,所以不會互相干擾。
複製程式碼

三、如何編寫具有可重入性的函式

       1、在寫函式時候儘量使用區域性變數(例如暫存器、堆疊中的變數)。

       2、如果確實需要訪問全域性變數(包括static),一定要注意實施互斥手段。可重入函式在並行執行環境中非常重要,但是一般要為訪問全域性變數付出一些效能代價。編寫可重入函式時,若使用全域性變數,則應通過關中斷、訊號量(即P、V操作)等手段對其加以保護。

四、函式的可重入性和執行緒安全的關係

        可重入與執行緒安全兩個概念都關係到函式處理資源的方式。但是,他們有一定的區別。可重入概念會影響函式的外部介面,而執行緒安全只關心函式的實現。

大多數情況下,要將不可重入函式改為可重入的,需要修改函式介面,使得所有的資料都通過函式的呼叫者提供。要將非執行緒安全的函式改為執行緒安全的,則只需要修改函式的實現部分。一般通過加入同步機制以保護共享的資源,使之不會被幾個執行緒同時訪問。

        執行緒安全與可重入性是兩個不同性質的概念。

        可重入是在單執行緒作業系統背景下,重入的函式或者子程式,按照後進先出的線性序依次執行完畢。多執行緒執行的函式或子程式,各個執行緒的執行時機是由作業系統排程,不可預期的,但是該函式的每個執行執行緒都會不時的獲得CPU的時間片,不斷向前推進執行進度。

        可重入函式未必是執行緒安全的;執行緒安全函式未必是可重入的。例如,一個函式開啟某個檔案並讀入資料。這個函式是可重入的,因為它的多個例項同時執行不會造成衝突;但它不是執行緒安全的,因為在它讀入檔案時可能有別的執行緒正在修改該檔案,為了執行緒安全必須對檔案加“同步鎖”。

        函式在它的函式體內部訪問共享資源使用了加鎖、解鎖操作,所以它是執行緒安全的,但是卻不可重入。因為若該函式一個例項執行到已經執行加鎖但未執行解鎖時被停下來,系統又啟動該函式的另外一個例項,則新的例項在加鎖處將轉入等待。如果該函式是一箇中斷處理服務,在中斷處理時又發生新的中斷將導致資源死鎖。

【本部落格 http://www.cnblogs.com/iTsihang 中原創之博文,版權屬作者所有,歡迎轉載。轉載之時請保留本段內容,否則作者將保留追究版權之權利】