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