Linux中的可重入函式和不可重入函式

2021-07-23 16:01:09 字數 3772 閱讀 9877

標籤:linux

多執行緒處理器

行業資料

全域性變數

2013-04-18 10:25

3484人閱讀

收藏舉報

分類:《unix環境高階程式設計》(55)

作者同類文章

x可重入函式

可重入函式(即可以被中斷的函式)可以被乙個以上的任務呼叫,而不擔心資料破壞。可重入函式在任何時候都可以被中斷,而一段時間之後又可以恢復執行,而相應的資料不會破壞或者丟失。

可重入函式使用的變數有兩種情況:

1.使用區域性變數,變數儲存在cpu暫存器中或者堆疊中;

2.使用全域性變數,但是這時候要注意保護全域性變數(防止任務中斷後被其它任務改變變數)。

?

1

2

3

4

5

voidstrcpy(*dest,*src)

while(*

dest++ = *src ++)

*dest

= nul;

分析:上面的函式用於字串複製,而引數是存放在堆疊中的,故而改函式可以被多工呼叫,而不必擔心各個任務呼叫期間會互相破壞對方的指標。

基本上下面的函式都是不可重入的:

1.函式內使用了靜態的資料。

2.函式內使用了malloc()或者free()函式的。

3.函式內呼叫了標準的i/o函式的。

?

1

2

3

4

5

6

7

inttemp;

voidswap(int*ex1,int*ex2)

temp

= *ex1;//(1)

*ex1

= *ex2;

*ex2

= temp;

分析:該函式中的全域性變數temp是的函式變成了乙個不可重入的函式,因為在多工系統中,假如在任務1中呼叫swap函式,而程式執行到(1)處時被中斷,進而執行其它的任務2,而剛好任務2也呼叫了swap函式,則temp裡存的值則會被任務2改變。從而回到任務1被中斷處繼續執行的時候,temp裡存的值已經不再是原來存的temp值了,進而產生了錯誤。

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

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

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

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

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

不可重入函式

在多工系統下,中斷可能在任務執行的任何時間發生;如果乙個函式的執行期間被中斷後,到重新恢復到斷點進行執行的過程中,函式所依賴的環境沒有發生改變,那麼這個函式就是可重入的,否則就不可重入。

在中斷前後不都要儲存和恢復上下文嗎,怎麼會出現函式所依賴的環境發生改變了呢?

我們知道中斷時確實儲存一些上下文,但是僅限於返回位址,cpu暫存器等之類的少量上下文,而函式內部使用的諸如全域性或靜態變數,buffer等並不在保護之列,所以如果這些值在函式被中斷期間發生了改變,那麼當函式回到斷點繼續執行時,其結果就不可預料了。

滿足下面條件之一的多數是不可重入函式:

(1)使用了靜態資料結構;

(2)呼叫了malloc或free;

(3)呼叫了標準i/o函式;

(4)進行了浮點運算.

malloc/free是不可重入的,它們使用了全域性變數來指向空閒區;標準i/o庫的很多實現都使用了全域性資料結構; 許多的處理器/編譯器中,浮點一般都是不可重入的

(浮點運算大多使用協處理器或者軟體模擬來實現)。

在訊號處理程式及多執行緒程式設計時,要特別注意。

考慮這種情況:

1) 訊號處理程式a內外都呼叫了同乙個不可重入函式b;b在執行期間被訊號打斷,進入a (a中呼叫了b),完事之後返回b被中斷點繼續執行,這時b函式的環境可能改變,其結果就不可預料了。

2) 多執行緒共享程序內部的資源,如果兩個執行緒a,b呼叫同乙個不可重入函式f,a執行緒進入f後,執行緒排程,切換到b,b也執行了f,那麼當再次切換到執行緒a時,其呼叫f的結果也是不可預料的。

在訊號處理程式中即使呼叫可重入函式也有問題要注意。作為乙個通用的規則,當在訊號處理程式中呼叫可重

入函式時,應當在其前儲存errno,並在其後恢復errno。(要了解經常**捉到的訊號是sigchld,其訊號處理程式通常要呼叫一種wait函式,而各種wait函式都能改變errno。)頂1

踩0  

linux系統呼叫和庫函式呼叫的區別

linux c 之sigsuspend 程序阻塞

我的同類文章

《unix環境高階程式設計》(55)

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

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

可重入和不可重入函式

把乙個不可重入函式變成可重入的唯一方法是用可重入規則來重寫它。其實很簡單,只要遵守了幾條很容易理解的規則,那麼寫出來的函式就是可重入的。1 不要使用全域性變數。因為別的 很可能覆蓋這些變數值。2 在和硬體發生互動的時候,切記執行類似disinterrupt 之類的操作,就是關閉硬體中斷。完成互動記得...

可重入函式和不可重入函式

可重入函式 可重入函式主要用於多工環境中,乙個可重入函式簡單來說是可以被中斷的函式,即可以在函式執行的任何時刻中斷它,轉入os排程下去執行另一段 而返回控制時不出現錯誤,這意味著它除了使用自己棧上的變數以外,不依賴於任何環境 包括static 這樣的函式就是purecode 純 可重入,它可以允許該...