Linux 可重入函式與不可重入函式

2021-08-18 20:45:53 字數 1756 閱讀 5478

函式是一段載入到記憶體的**。函式的**可長可短,執行時間長度也不確定。在多執行緒中,執行緒之間是可以進行切換的。函式是一段寫好的**,屬於程式公有的**段。乙個程序中有多個執行緒,每乙個執行緒都可以呼叫這段函式**執行。而在多執行緒環境中,執行緒的切換是無法預料的,你不知道下一秒是哪個執行緒在執行,每時每刻的執行環境都不一樣,因為執行緒切換也是變化莫測的。這是作業系統排程程序執行緒的範圍,不是我們能夠掌控的。既然我們無法改變程序排程,無法得知執行緒切換的規律,那就不要依賴執行緒的切換。我們的程式要做到,無論執行緒怎麼切換,執行的結果都要一致。而我們該如何才能夠達到無論執行緒如何切換,執行結果都是一致的呢?

重入:重複進入!!!

乙個函式在執行的過程中被打斷,然後會再被再重頭執行一次,執行完後,再回來把剛才沒執行完的部分執行完。這就相當於巢狀的執行了。函式是公共**,這樣的執行是允許的。函式的執行可以被打斷,打斷之後還可以再重頭執行,執行完後接著執行剛才沒有執行的**,然後第一次執行的**(被打斷的函式)執行結果還是正確的。也就是說,這個函式執行,無論中間把這個函式再嵌入執行多少遍,怎麼嵌入,最終執行完,執行的結果都是正確的,這樣的函式就是可重入函式。

我們平常所寫的函式,常常都是用的函式內部的區域性變數,由於是函式內部的區域性變數,那麼如果出現了函式在執行的過程中被打斷,然後被重頭執行,執行完畢後,由於我們使用的都是函式內部的區域性變數,而函式執行完畢,會釋放在函式內部所建立的區域性變數等,這樣等我們返回到之前被中斷的地方去的時候,就不會影響此時這個函式的內部的變數內容,這樣的話,也就是說我們函式為可重入的。

void my_strcpy(*dest, *src)

*dest = '\0';

}

比如,像我們平常所寫的這類函式,函式在棧上建立,如果此函式被重入,多次重入時,互相之間並不會影響它們的指標指向。所以在重入時是可以的。

常用的可重入函式的方法有:

1.不要使用全域性變數,防止別的**覆蓋這些變數的值。

2.呼叫這類函式之前先關掉中斷,呼叫完之後馬上開啟中斷。防止函式執行期間被中斷進入別的任務執行。

3.使用訊號量(互斥條件)。

總而言之:要保證中斷是安全的。

那麼不可重入函式顯而易見,就是在函式執行期間,被中斷,從頭執行這個函式,執行完畢後再返回剛才的中斷點繼續執行,此時由於剛才的中斷導致了現在從新在中斷點執行時發生了不可預料的錯誤。那麼這類函式就是不可重入函式。

我們知道,在中斷函式之後會將中斷點的一些資料儲存起來,上下文資料等等,那麼這些資料不是被儲存了嗎?怎麼還會被影響?其實我們在儲存上下文資料的時候,僅僅儲存了一小部分,而且那一小部分也只是位址,而對全域性變數、靜態變數這些並沒有儲存。所以一旦中斷之後,返回到中斷點,此時就是不可預料的了。

常見的不可重入函式:

使用了靜態資料結構

呼叫了malloc和free等

呼叫了標準i/o函式

進行了浮點運算

malloc與free是不可重入的,它們使用了全域性變數來指向堆區。標準i/o大多都使用了全域性資料結構。浮點一般都是不可重入的 (浮點運算大多使用協處理器或者軟體模擬來實現)。

不使用或者互斥使用全域性變數,不使用靜態區域性變數,只是用區域性變數,在函式中動態分配的記憶體只在本函式中使用,不會傳遞函式外使用,只要保證區域性特性,函式中使用的所有東西都只有區域性性,對外不公開,用完即釋放,就可以保證可重入。這樣,不管怎麼重疊,反正本層的函式的東西只有本層能夠使用,其他層的函式無法使用,就相當於隔離每一層的變數。這樣,不管重疊多少次,都不可能相互影響。這樣每一層函式執行的結果都是正確的。

Linux 可重入函式 不可重入函式

當我們在使用malloc函式的時候,如果有訊號中斷了我們malloc操作,假設malloc剛剛從堆上的空閒鏈上找到合適的位置,結果打斷後去執行其他操作,剛好其他操作裡也有malloc,也恰好找到了剛剛malloc的地方,把那個空間從空閒空間鏈上取下,然後其他操作結束,返回。此時主函式內的那個mall...

可重入函式與不可重入函式

可重入 reentrant 函式可以由多於乙個任務併發使用,而不必擔心資料錯誤。相反,不可重入 non reentrant 函式不能由超過乙個任務所共享,除非能確保函式的互斥 或者使用訊號量,或者在 的關鍵部分禁用中斷 可重入函式可以在任意時刻被中斷,稍後再繼續執行,不會丟失資料。可重入函式要麼使用...

可重入函式與不可重入函式

可重入 可重新進入,也即兩次進入的現場一模一樣?在實時系統的設計中,經常會出現多個任務呼叫同乙個函式的情況。如果這個函式不幸被設計成為不可重入的函式的話,那麼不同任務呼叫這個函式時可能修改其他任務呼叫這個函式的資料,從而導致不可預料的後果。那麼什麼是可重入函式呢?所謂可重入是指乙個可以被多個任務呼叫...