國產化平臺上應用程序進程異常退出故障分析_第1頁
國產化平臺上應用程序進程異常退出故障分析_第2頁
國產化平臺上應用程序進程異常退出故障分析_第3頁
國產化平臺上應用程序進程異常退出故障分析_第4頁
國產化平臺上應用程序進程異常退出故障分析_第5頁
已閱讀5頁,還剩6頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

0引言近幾年,隨著國內信息安全事件頻繁發生,加之相關國家對關鍵技術的封鎖,國家倡導并推動核心技術實現自主可控。在這樣的背景下,國產CPU的發展和應用得到了國家的高度重視。目前,國產CPU正處于快速追趕的關鍵階段,初步構建起了完整的產品線和上下游全產業鏈生態體系。在國家大力推進國產化替代工程的環境下,諸多項目開始從非國產化平臺移植到國產化平臺,期間不可避免出現了一些問題。本文結合某具體項目,針對一個國產CPU弱一致性存儲模型引起的進程異常退出問題進行了深入分析,并給出了解決措施。1故障概述某國產服務器設備在穩定運行1年后出現應用軟件進程異常退出的故障,導致系統功能無法正常使用。該設備為全國產化設備,基礎設施平臺中CPU、操作系統以及數據庫等均選取國內廠家的型號產品。自主研發的應用軟件在原非國產化平臺運行穩定可靠,在從非國產化平臺移植到國產平臺時,上述設備出現故障。該設備在使用時需要做到“多任務,高并發,高可靠”,需要同在同一時間處理多任務、并發消息,具有高吞吐量和低延時,且7×24h無故障運行。2故障分析故障發生后,遠程登錄設備,查看到數據庫和操作系統運行正常,且在進程退出的同時生成了系統內核文件(coredump)。通過gdb工具將進程退出時運行狀態翻譯為調用棧,可以看出進程退出時處理線程使用關鍵字delete來釋放內存,最終調用free時發生異常導致進程退出(abort)。通過Linux系統編程手冊中free()函數的描述可以看出,釋放一塊未被分配的內存會導致系統工作異常。通過上文對故障現場數據的分析可以判定,故障現場的進程退出是由于釋放一塊未被分配的內存造成的,即定位問題的關鍵是找到“釋放一塊未被分配內存”的原因。結合代碼實現,整理故障分析樹如圖1所示。圖1故障分析樹故障出現時釋放的內存是用于存放業務數據的,相關業務數據的流轉軌跡如圖2所示。當發送線程接收完來源數據后,申請一塊內存來構造業務數據,然后通過消息隊列發送到處理線程;處理線程根據數據結構解析業務數據并進行分類處理,處理完成后釋放業務數據對應的內存;當消息隊列滿時,發送線程需要釋放業務數據的內存。圖2業務數據流轉軌跡對于業務數據的流轉過程和代碼實現,以下幾個環節構成問題分析的完整路徑:業務數據對應內存的申請、釋放過程;業務數據對應的內存指針的使用過程、業務數據對應的指針從內存申請成功到被釋放之間是否被改動過,由此得出如圖1所示的故障分析樹。針對該故障分析樹具體排查如下。2.1內存指針使用錯誤(M1)通過指針顯示使用內存時,如果未能正確處理,往往會導致指針指向一塊未被分配的內存,而釋放這個指針會導致當前問題的出現。未能正確處理有很多表現形式,常用的且與本項目相關的幾點包括內存申請失敗的處理和直接使用指針時運算錯誤,導致使用未被分配的內存,詳見X1、X2。2.1.1申請內存失敗(X1)從業務數據流轉軌跡圖(圖2)可以看到,在構造業務數據前有申請內存的操作。如果申請內存失敗,同時未做好失敗處理,可能導致非法使用內存,從而釋放未被分配的內存。此時,可以通過代碼走讀的方式遍歷所有申請內存的位置,查看申請內存失敗時是否有非法使用內存的情況。該項目未發現申請內存失敗時有非法使用內存的情況。2.1.2指針偏移計算錯誤(X2)從業務數據流轉軌跡圖(圖2)可以看出,有多個地方訪問內存。如果通過指針運算來直接訪問內存,在運算出錯時會導致非法使用內存。此時,可以通過靜態代碼檢查工具(如Klockwork8)對程序代碼進行掃描或對代碼進行人工走查,著重檢查指針偏移量的情況、計算的準確性、字節對齊以及數據結構定義的一致性等,查看是否存在問題。該項目未發現上述問題。所以可以排除X2。2.2內存重復釋放(X3)內存申請、釋放過程中出現重復釋放,導致再次被釋放的內存是未被分配的內存。根據業務數據流轉軌跡圖(圖2)可見,可能重復釋放內存的情況是發送線程將業務數據送入隊列時消息隊列已滿,拒絕將業務數據存入隊列,發送線程將該業務數據釋放,此時消息隊列仍將該業務數據復制了一份到處理線程,從而引起處理線程重復釋放內存。針對上述懷疑,可以編寫一組測試程序來確認消息隊列滿時是否將已經拒絕的業務數據復制一份到處理線程。結果顯示:在消息隊列滿的情況下,不會有復制的數據送給處理線程,故排除處理線程重復釋放業務數據內存的情況。2.3內存指針被修改(M2)業務數據對應內存的指針在系統運行過程中被修改,根據業務數據流轉軌跡圖(圖2)需要分3個階段排查,分別為進入消息隊列前(X4)、在消息隊列中(X5)和出消息隊列后(X6)。2.3.1消息隊列前被修改(X4)如果業務數據的內存指針在進入消息隊列前被修改,那么修改后的指針很可能指向一塊未被分配的內存。為了確認是否存在該問題,在原程序中添加調試代碼來跟蹤業務數據內存指針的變化情況。調試代碼分別添加在申請內存成功處和消息對列入口處。在測試環境中進行問題復現,當問題出現時對比兩處的指針。結果顯示,指針未被修改,如圖3所示,排除X4。圖3申請內存與放入隊列前對比2.3.2消息隊列中被修改(X5)設備軟件采用自己構建的消息隊列模塊實現線程間通信。該模塊具有高吞吐量和低延時的特點,廣泛應用于通信系統的信令控制、媒體轉發以及業務調度等軟件中。圖4描述了該消息隊列中關于內存及指針的處理過程,即業務數據的指針被發送線程傳入消息隊列,消息隊列會把這個指針存儲到指針數組。當處理線程需要獲取業務數據時,消息隊列會把該業務數據指針返回給處理線程。圖4消息隊列內存及指針處理過程在消息隊列入口、寫指針數組以及消息隊列出口3處增加調試代碼,記錄業務數據指針.問題出現時對比3處記錄,以判斷指針是否被修改。實驗發現:消息隊列入口處與寫指針數組處的指針相同;消息隊列出口處的指針與消息隊列入口處不同。根據實驗結果,問題定位需要聚焦在消息隊列出口處讀到的業務數據指針與寫指針數組時不同的原因。為了分析指針在隊列的傳輸中被改變的原因,在原代碼中增加調試代碼,當問題出現時觀測到的情況如圖5所示。圖5消息隊列調試處理過程①在時間點T1時,寫線程向消息隊列指針Index62處寫入數據Data1。寫操作執行結束后,通知讀線程有數據可讀,同時讀線程從消息隊列中讀取指針Index62處數據(標記為Data3),發現Data3≠Data1,卻與上一次寫入的數據Data5相等。②為了確認Data1數據是否寫入指針Index62處,寫線程在數據寫入完成后,讀取指針Index62處的數據(標記為Data2),發現Data2=Data1,確認Data1數據已經寫入指針Index62處。此時的時間點標記為T2。③讀線程再次從消息隊列中讀取指針Index62處數據(標記為Data4),發現Data4=Data1。此時的時間點標記為T3。綜上所述,讀到的錯誤指針是隊列中的“舊”值。再次讀取該地址可以讀到正確指針,證明指針讀取錯誤是由內存刷新延遲造成的。經過與CPU廠家技術人員共同分析,本項目中的內存刷新延遲可能與國產CPU架構弱一致性存儲模型有關,同時給出了驗證方案,即增加內存屏障,對比使用前后內存刷新延遲的情況。內存屏障用于保證操作有序,屏障之前的操作一定會先于內存屏障之后的操作。根據原程序的架構擬制了驗證程序,功能包括:3個寫線程向隊列中寫入指針,寫入時打印指針地址;1個線程從隊列中讀取指針,讀取到指針后打印指針地址。在該程序代碼中加入了內存屏障,通過對比打開和關閉內存屏障的結果,進行問題原因驗證。①開啟內存屏障,未出現內存刷新延遲,程序運行正常;②關閉內存屏障,出現內存刷新延遲。據此證明內存刷新延遲是由弱一致性存儲模型造成的。2.3.3消息隊列后被修改(X6)如果業務數據的內存指針在出消息隊列后被修改,修改后的指針很可能指向一塊未被分配的內存。為了確認指針是否被修改,可以在原程序中添加調試代碼來跟蹤業務數據內存指針的變化情況。在消息對列出口處和釋放內存前記錄內存指針,對比觀測結果,兩處指針相同,指針在出隊列后未被修改,排除X6。2.4故障定位結果通過以上故障樹分析和實驗結果得知,故障的根本原因是該國產CPU采用的是弱一致性存儲模型,在與其適配過程中應用軟件未做內存屏障,引起應用軟件讀到錯誤指針,致使一塊未被分配的內存被釋放而應用軟件進程退出故障。3機理分析消息隊列模塊廣泛應用于通信系統的信令控制、媒體轉發以及業務調度等軟件中,在x86、ARM和PowerPC等架構處理器上穩定運行多年,最大特點是高吞吐量和低延時。為了實現上述特點,在數據結構、指針數組管理和并發處理上做了很多優化,如消息隊列的讀寫同步通過指針數組的計數變量來實現,可以極大地減少系統開銷。但是,這個優化在多核系統中對緩存的一致性有很大挑戰。本項目使用的國產CPU芯片有4個核,每個核包含獨有的指令緩存(I-Cache)、一級緩存(D-Cache)和二級緩存(V-Cache),4個核之間通過交叉互聯網絡與三級緩存(S-Cache)相連,進而再通過另一個交叉互聯網絡與內存相連。該國產CPU采用GS464E處理器核,實現的是弱一致性存儲模型。該國產CPU對弱一致性存儲模型的描述為“弱一致性存儲模型,即多條不相關的加載指令或存儲指令的返回結果的到達的先后次序跟處理器內部數據通路的暢通性有關系,不一定按照發出的次序依次返回,這不影響訪存操作的正確性。如果程序具有顯式的因果關系,弱序一致性一定會尊重這種序關系,否則亂序有可能會打破原有的程序邏輯,就需要使用屏障來抑制亂序,以維持程序所期望的邏輯”。由此可知,弱一致性的影響與處理器內部數據通路的暢通性有關。在CPU內部數據通路繁忙時,會概率性地出現無顯式因果關系的代碼被亂序執行。根據業務數據流轉軌跡圖(圖2),結合原程序中的相關代碼,在故障發生時,弱一致性存儲模型在多核系統中的讀寫行為如圖6左側所示。圖6弱一致性存儲模型在多核系統中的讀寫行為和加入內存屏障后的讀寫行為應用程序軟件寫線程利用Fifo[NextIn]=A將業務數據指針(A)存入消息隊列,然后利用NextIn=(NextIn+1)通知讀線程取出業務數據指針。在CPU內部數據通路繁忙時,弱一致性會概率性導致如下情況:讀線程先讀到已經NextIn=(NextIn+1)的數據,再通過Fifo[NextOut]讀取業務數據指針(A)的數據,此時數據A還未完成存儲,當前Fifo[NextOut]中的值還是上一輪存儲的“舊數據”。這個舊數據指向的是一塊未被分配的內存,如果被處理線程釋放會引起“釋放一塊未被分配的內存”錯誤。內存屏障用于保證操作有序,屏障之前的操作一定會先于內存屏障之后的操作。大多數現代計算機為了提高性能而采取亂序執行,使得內存屏障成為必須。工程實現上,它經常應用于對存儲時序有嚴格要求的場景。圖6右側結合原程序中的相關代碼描述了加入內存屏障后弱一致性存儲模型在多核系統中的讀寫行為。內存屏障會保證寫線程將業務數據指針存入消息隊列指令(Fifo[NextIn]=A)先于通知讀線程指令(NextIn=(NextIn+1))執行,從而保證讀線程能獲取到正確的業務數據指針進行處理。4解決措施在原應用程序中增加內存屏障,針對整改后的應用軟件版本,采用故障復現時同樣的測試環境、測試數據和測試方法進行驗證。驗證包括“驗證測試”和“極限測試”兩部分。其中,“驗證測試”的目的是驗證在設計指標下程序是否穩定運行;“極限測試”的目的是驗證在超過軟件處理能力的條件下

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論