函数的可重入性理解
一、維基百科解釋
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 中原創之博文,版權屬作者所有,歡迎轉載。轉載之時請保留本段內容,否則作者將保留追究版權之權利】總結
- 上一篇: 关于C++模版的连接错误问题
- 下一篇: 高级数据结构研究-B树系列以及红黑树