函式不可訪問 關於可重入函式

2021-10-12 08:06:35 字數 1146 閱讀 1040

最近在公司維護的專案中碰到乙個解決了定位很久的 bug , bug 找到的時候發現犯了很低階的錯誤——在中斷處理函式中呼叫了 printf 函式,因為中斷處理函式的呼叫了不可重入函式,導致中斷丟失和系統位置錯誤,這裡直接導致嵌入式 linux 系統應用程序中的所有執行緒停掉,進而導致看門狗程序得不到餵狗,裝置重啟。

就以上三個問題展開小短文:

可重入函式主要用於多工環境中,乙個可重入的函式簡單來說就是可以被中斷的函式,也就是說,可以在這個函式執行的任何時刻中斷它,轉入 os 排程下去執行另外一段**,而返回控制時不會出現什麼錯誤;而不可重入的函式由於使用了一些系統資源,比如全域性變數區,中斷向量表等,所以它如果被中斷的話,可能會出現問題,這類函式是不能執行在多工環境下的。

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

void strcpy(char *lpszdest, char *lpszsrc) 

char ctemp;    ///void swapchar1(char *lpcx, char *lpcy) 

void swapchar2(char *lpcx,char *lpcy)

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

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

在中斷處理函式中呼叫有互斥鎖保護的全域性變數,如果恰好該變數正在被另乙個執行緒呼叫,會導致中斷處理函式不能及時返回,導致中斷丟失等嚴重問題。

並且在多執行緒環境中使用,在沒有加鎖的情況下,對同一段記憶體塊進行併發讀寫,就會造成 segmentfault/coredump 之類的問題。

總而言之,中斷處理函式做的事情越簡單越好。

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

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

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

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

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

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