1前言最近,我在公司維護的項目中遇到了一個已修復了很長時間的錯誤。
發現錯誤后,發現發生了非常低級的錯誤-在中斷處理函數中調用了printf函數,因為未調用中斷處理函數。
重入功能會導致中斷損失和系統位置錯誤。
這直接導致嵌入式linux系統應用程序進程中的所有線程停止,進而導致看門狗進程無法喂狗,并且設備重新啟動。
那么什么是不可重入函數?為什么中斷處理程序不能直接調用非可重入函數?如何編寫可重入函數?就以上三個問題開始一篇簡短的文章:2什么是不可重入函數?可重入函數主要用于多任務環境中。
可重入功能只是可以中斷的功能,也就是說,可以在執行此功能期間隨時將其中斷,然后將其轉移到OS中以進行執行。
一段代碼,返回控制不會有錯誤;非可重入函數使用某些系統資源,例如全局變量區,中斷向量表等,因此,如果該函數被中斷,則可能會發生問題。
函數不能在多任務環境中運行。
滿足以下條件的大多數函數都是不可重入的:函數主體中使用了靜態數據結構;在函數體中調用malloc()或free();在功能體中調用標準I / O功能; A.是可重入函數void&strcpy(char& nbsp; * lpszDest,& nbsp; char& nbsp; * lpszSrc)& nbsp; {& nbsp;& nbsp;& nbsp;& nbsp; while(* lpszDest ++ = * lpszSrc ++); ///& lt;& nbsp;使用的局部變量& nbsp;& nbsp;& nbsp; * dest = 0;} B.非可重入函數1 char  cTemp;& nbsp;& nbsp;& nbsp; ///<& nbsp;全局變量void& nbsp; SwapChar1(charap& nbsp; * lpcX, & nbsp; char& nbsp; * lpcY)& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; cTemp = * lpcX;& nbsp;& nbsp;& nbsp;& n ; nbsp; * lpcX = * lpcY;& nbsp;& nbsp;& nbsp; lpcY = cTemp; <& nbsp; ///& lt;& nbsp;訪問的全局變量} C.非可重入函數2 void& nbsp; SwapChar2(char& nbsp; * lpcX,char& nbsp ; * lpcY){& nbsp;& nbsp;& nbsp; static& nbsp; char& cTemp;& nbsp; ///& lt;& nbsp;靜態局部變量& nbsp;& nbsp;& nbsp;& nbsp; cTemp = * lpcX;& n  & nbsp;& nbsp; * lpcX = * lpcY;& nbsp;& nbsp;& nbsp;& nbsp; lpcY = cTemp;& nbsp;& nbsp;& nbsp; ///& lt;& nbsp;使用的靜態局部變量} 3為什么中斷處理程序不能直接調用非可重入函數?在多任務系統中,中斷可能在任務執行期間的任何時間發生;如果某個函數的執行被中斷,則該函數所依賴的環境在還原到要執行的斷點的過程中沒有更改,則該函數為可重入的,否則不能為可重入的。
您不必在中斷之前和之后保存并還原上下文嗎?功能所依賴的環境如何變化?我們知道,某些上下文在中斷時會保存,但僅限于少量上下文,例如返回地址,cpu寄存器等,以及函數的內部使用(例如全局或靜態變量,緩沖區等)。
沒有被保護,所以如果這些值在函數中發生在中斷期間的更改,那么當函數返回到斷點以繼續執行時,結果是不可預測的。
如果在中斷處理函數中調用了由互斥鎖保護的全局變量,則在另一個線程正在調用該變量時,中斷處理函數將無法及時返回,從而導致嚴重的問題,例如中斷丟失。
而且,在多線程環境中使用時,在不鎖定的情況下并發地讀取和寫入同一內??存塊將導致諸如段錯誤/核心轉儲之類的問題。
總而言之,中斷處理程序函數越簡單越好。
4如何編寫可重入函數?這些全局變量不在函數主體中訪問;如果必須訪問全局變量,請記住使用互斥信號量來保護全局變量。
或者在調用此函數之前關閉中斷,然后在調用之后打開中斷;不要使用靜態局部變量;堅持只使用默認狀態(自動)局部變量;與硬件交互時,請記住關閉硬件中斷。
完成交互后,請記住打開中斷。
在某些系列中,這被稱為“進入/退出核心”。
或由OS_ENTER_KERNAL / OS_EXIT_KERNAL描述;您不能調用任何非可重入函數;我們