史佳龍,朱怡安,陸 偉,柴瑞亞
1.西北工業大學 計算機學院,西安 710072
2.西北工業大學 軟件與微電子學院,西安 710072
隨著各類嵌入式系統應用日益廣泛,對其可靠性和安全性的需求也隨之提高[1-2]。具備自愈能力的操作系統可在無需人工干預的情況下自動發現、診斷并修復故障,進而使得操作系統在遭遇系統失效時,還能夠繼續為用戶程序提供服務,可以有效減少當前操作系統內核在出現故障部分或全部服務失效時帶來的損失[3],對提高系統可靠性有重要的意義。自愈操作系統中將系統的自愈過程抽象為監測、診斷和恢復三個自主元素,作為自愈操作系統對故障的感知手段,故障監測可以使操作系統具備自主發現故障的能力[4],是自愈操作系統實現自主故障定位診斷及恢復的基礎,在自愈操作系統研究中具有重要的意義。當前已有的操作系統故障監測技術大都需要硬件支持或對系統代碼進行修改,本文根據已有研究中對操作系統內核故障分類和故障點分布的研究,針對內核中動態內存分配和資源競爭相關故障提出了一種基于動態追蹤的故障監測技術,在Linux操作系統中該機制利用操作系統支持的斷點機制以可加載內核模塊的形式實現,不需要對原系統進行擴展或修改,并通過故障注入實驗對提出的監測技術的有效性從故障檢測率、誤報率、系統負載和監測延時幾方面進行了驗證。
操作系統故障監測技術可分為基于異常事件、基于時間和基于系統性能指標三類。基于異常事件的監測技術主要通過感知系統中出現的異常事件來進行故障感知[5],其能夠監測的故障類型有限,且一般需要對原系統代碼進行修改;基于時間的監測典型代表為定時器機制[6],當系統出現故障導致定時器未被周期性重置時,則認為操作系統或某個部件出現故障,無法精確診斷出現了何種故障以及定位故障點,有時需要在原有系統中增加必要的軟件模塊或特定硬件;基于系統指標的監測技術通過對整體操作系統性能指標異常值的監測實現對故障的監測[7-8],通過故障映射模型實現較為精確的故障診斷,但模型的建立大都需要訓練過程以達到較好的監測效果,可移植性無法得到保證。
已有研究中在設計故障監測技術時,大都沒有對目標系統的故障分類和分布進行分析,故其適用性無法得到保證,當前已有的基于語義匹配的代碼靜態分析[9-10]和利用操作系統崩潰現場數據進行故障點分析[11]的研究結果表明,操作系統中的故障往往集中分布在特定內核位置。針對在操作系統中內核故障造成影響較應用程序故障更為嚴重的問題,Deshpande等人[12]進一步將操作系統的故障歸結為以下四類:非法指針訪問、程序邏輯中預先設定的崩潰點、內存泄露、同步機制的不恰當使用導致的資源競爭。四類故障中,除去人為設定的內核崩潰點,內核中的故障點集中于內存分配使用及回收、資源競爭同步等方面,且非法指針的訪問造成在很多情形下是由于內存分配使用不當、同步不當導致的數據覆蓋造成的。在Linux中由于內核程序共享執行空間,單點的故障會傳播到整個內核進而影響其他程序的執行,甚至造成系統整體失效[13]。
針對Linux操作系統,基于以上內核故障點的分析,本文將內核中內存分配和資源競爭操作相關的故障作為主要監測目標,而此類操作在內核中往往表現為統一的方法調用(將其定義為內核關鍵方法),因此故障的產生與關鍵方法的不恰當使用存在直接的因果關系。通過動態追蹤內核方法調用,可以對導致內核全局數據狀態遷移的方法調用進行記錄,依據設定的規則對記錄的調用序列和數據進行分析,可實現對故障的監測和定位。圖1中為本文提出的基于動態追蹤的故障監測架構,內核動態追蹤機制由三部分構成,監測斷點定義模塊設定需要監測的關鍵方法;監測數據采集模塊用于記錄系統調用的執行序列,將每次方法調用的內核上下文信息以及調用參數、返回值信息存儲到監測信息鏈表中;故障診斷模塊依據追蹤信息和設計的規則進行故障診斷并輸出診斷結果。

圖1 內核動態追蹤機制架構
自旋鎖機制是操作系統中廣泛使用的一種資源同步機制,已有的研究成果中也將其列為主要故障點,根據內核動態追蹤架構,圖2中描述了操作系統中監測自旋鎖相關故障的過程,通過在自旋鎖獲取內核方法和自旋鎖釋放內核方法調用前后設置監測斷點,可以對內核中獲取和釋放自旋鎖的操作信息進行記錄,并通過全局鏈表的方式進行保存,在進行內核信息采集時,需要注意分析當前方法調用導致的內核狀態變化,確定斷點處理程序類型為應當在關鍵方法之前或者之后執行,如當使用__raw_spin_lock_bh獲取自旋鎖時會關閉系統軟中斷,此時若要監測鎖釋放操作__raw_spin_unlock_bh則斷點處理程序應當在釋放鎖關鍵方法之后執行,因為內核在關中斷的狀態下操作監測數據鏈表可能導致內核卡死。在進程調用do_exit方法退出時,檢查監測隊列中是否存在于當前要退出進程相關的記錄,通過對記錄中的信息分析進行故障診斷。

圖2 內核自旋鎖故障監測實例
Hector[13]、Lockout[14]使用代碼靜態分析的方法也實現了對內核故障點的追蹤,但實際系統在運行過程中時,由于內核中中斷、搶占等機制的存在,靜態代碼分析的故障追蹤并不能完全發現系統中可能存在的故障,而本文中提出的監測技術可以偵測到內核中實際的調用序列和上下文信息,對故障實現更為有效的監測。
故障監測器由監測模塊和數據顯示兩個主要模塊構成,其中監測模塊以可加載內核模塊的形式實現,可以根據需求動態地加載到內核中運行,針對不同類型的故障可同時加載多個故障監測器,而數據顯示模塊在用戶態實現,顯示界面使用wxPython程序庫設計實現,實現故障監測結果的顯示,兩個模塊以系統日志為數據交互媒介。故障監測模塊的實現包括監測點、監測數據鏈表和斷點處理程序三部分,其中監測點可定義為Jprobe、Kretprobe和Kprobe三類,分別用于獲取內核調用參數、返回值以及調用棧信息;監測數據鏈表用于存儲監測信息;斷點處理程序根據采集到的內核信息對監測數據鏈表進行維護,可令其在斷點發生之前或之后執行,在程序退出時分析監測數據鏈表數據,從而進行故障診斷。
以自旋鎖相關故障為例說明對資源競爭類故障的監測方法,主要是通過對鎖獲取函數、鎖釋放函數以及進程退出函數的監測實現對故障的定位診斷,其中使用的監測方法以及相應的斷點處理程序功能描述如表1所示。
對于監測到的每一次鎖操作,監測程序動態分配一個結構體來記錄鎖操作相關數據,監測記錄結構體中會記錄鎖指針、獲取鎖的進程以及鎖類型和當前進程執行上下文(flags),并維護一個監測記錄鏈表來記錄操作系統中當前鎖的申請釋放情況。在監測到某一個進程的釋放鎖操作后,查詢監測鏈表并將其中對應的信息刪除,在監測到某個進程的退出操作時(Linux中進程在退出時都會調用統一的接口do_exit),對監測鏈表執行相同查詢過程,若發現不存在該進程相關記錄,則說明該進程的鎖操作沒有出現獲取而沒有釋放的錯誤,否則說明當前進程在退出時沒有完全釋放其占有的鎖,可能造成資源競爭導致系統故障,此時監測程序會向系統日志中輸出相關的故障信息,供顯示模塊讀取。
同對資源競爭類故障的監測原理相同,對內核動態內存分配的監測是通過對vmalloc和vfree以及do_exit方法的監測實現的,具體說明見表2。
對于監測到的每一次動態內存分配操作,監測程序動態分配一個結構體來記錄內存操作相關數據,對于每一個動態內存分配操作,監測記錄結構體中會記錄分配的內存指針、獲取內存的進程并維護一個監測記錄鏈表來記錄操作系統中當前動態內存的申請釋放情況。監測鏈表的維護與自旋鎖監測鏈表類似,若監測到當前進程在退出操作后存在未釋放的內存時,說明當前進程出現了內存泄露故障,此時向系統日志輸出相應的故障信息。
關鍵方法監測模塊以內核模塊的形式根據監測需求動態加載到操作系統中在內核態運行,其監測信息會輸出到系統日志文件中,用戶態的顯示程序會以固定的時間間隔讀取日志文件中的信息,進行解析并顯示在程序界面中,如圖3中所示,從界面顯示框中用戶可以獲取內核中每個進程申請釋放鎖和內存的信息,如288號進程獲取了地址為f4a881eb的自旋鎖,根據3.2節和3.3節中描述的監測規則若監測到當前系統中出現故障,顯示模塊會從系統日志文件中讀取相應信息并顯示。

表1 自旋鎖相關操作監測方法列表

表2 內核動態內存分配相關操作監測方法列表

圖3 監測結果顯示界面
本文中采用故障注入實驗的方法對故障監測器的有效性從故障監測率、誤報率、系統的負載以及故障監測延時等方面進行分析驗證。實驗計算機配置為AMD速龍II雙核 P360(2.3 GHz雙核),2.0 GB內存,500 GB硬盤,內核版本為Linux 3.5。為了模擬系統真實的運行環境,在進行故障注入實驗時選取了Unixbench 5.1.2測評集模擬系統運行負載,選用了多個負載測試集以保證對內核關鍵方法調用的覆蓋率。故障庫以內核模塊的形式實現,在負載執行流中以一定的時間間隔動態加載到內核運行,并記錄監測到的故障總數,通過系統在加載故障監測器加載前后的Unixbench在各個負載集下的系統評分,可以對故障監測器對系統造成的負載做出評估。
故障注入實驗的故障庫包含資源競爭(鎖的不恰當使用如重復獲取同一個鎖、程序退出時不釋放占用的資源)和內存泄露故障,分別選取context1、dhry、fstime、shell8、pipe、spawn、syscall、excel等標準測試集作為負載,在其正常執行流內分別注入上述兩種類型的故障各50次,記錄每個負載執行流在完成時監測到的故障總數,結果如圖4所示,從結果中可知,監測器對79.25%的故障進行有效監測,但在shell8和execl負載流的執行上下文中不允許進行中斷操作,否則會導致內核中數據不一致問題,甚至出現oops現象,而本文中設計的監測技術則需要利用中斷產生斷點進行信息采集,因此監測器在此時無法對內存泄露類故障進行有效的監測。在shell8和spawn負載中會產生大量并發進程并分配到兩個CPU核上并發執行,由于每次創建進程退出進程操作都會執行斷點處理程序,在短時間內會觸發大量中斷,kprobe斷點機制在執行斷點處理程序之前會產生int3和debug中斷,在本實驗中會導致系統死機,因此在spawn和shell8負載流下對資源競爭類錯誤的監測效果較差。

圖4 故障注入實驗結果
在context1負載集下進行內存泄露故障監測時,監測到的故障總數超過了50次,雖然可能是由于操作系統中存在內存泄露故障造成的,但本文中將監測到的非人為注入的故障視為誤報,實驗結果表明監測器在監測到的636次故障中僅存在兩次誤報。
監測器對整體系統的負載主要是由于在內核中產生中斷采集監測信息以及對監測隊列數據的維護造成的,Unixbench可以給出的在不同負載流下實驗計算機在加載故障監測器前后的評分值,根據評分值可計算出監測器加載后系統性能下降了0.59%,故障監測器對系統造成的負載較小,具體評分值如圖5所示。

圖5 監測器負載分析結果
基于系統性能指標的故障監測技術中數據采樣周期的設置會直接影響到故障監測延時,對該類型故障監測器進行故障監測延時評估的時候往往通過設置不同的監測周期來進行實驗,研究[15]中提出的基于貝葉斯模型的進程級故障監測器在FDP和SWIMBOX兩類負載下的故障監測延時分別為(100.26±136.76)ms和(100±33.33)ms;基于系統I/O吞吐量進行故障監器[16]僅使用了I/O吞吐量這一個性能指標,且沒有復雜的故障判別模型,對于不同類型的故障監測延時差別較大,對于某些故障可能在很長的時間內無法進行有效的監測。

表3 基于時間的故障監測技術監測延時
基于時間的故障監測技術大都需要增加額外的硬件或者軟件機制支持定時機制,帶來了與具體進程或者系統的通信開銷,根據在使用管道、Socket、無線網絡三種通信方法[8]時其延時監測結果如表3中所示。
本文中提出的監測機制以內核模塊的形式實現,可以動態地加載到內核中運行,采用中斷的方式進行數據記錄和分析,減少了與特定進程或者硬件進行通信的開銷,故障監測延時實驗結果如圖6所示,從圖中數據可知,監測的延時明顯小于基于時間和系統指標的監測技術。由于對故障數據的采集和監測是通過中斷方式實現,監測的延時不會受到監測器具體配置的影響如性能指標采樣周期等。

圖6 監測器故障監測延時實驗結果
此外從實驗結果中可以看出,對資源競爭類故障的監測延時要明顯小于對內存泄露類故障的監測延時,這是由于資源競爭類故障往往和操作系統內的臨界區相關,為了提高系統的整體運行效率臨界區執行時間一般很短暫,且和多核中斷搶占上下文相關,因此可在臨界區執行結束退出時較快地偵測到故障,而對于內存泄露類的故障,由于其分配內存往往存在延時且可能導致該進程睡眠,因此對于此類故障監測的延時要長于資源競爭類故障。
故障監測技術為自愈操作系統提供對故障的自主感知能力,是故障診斷和恢復的基礎,根據已有的操作系統故障分布研究成果,本文提出了一種基于動態追蹤的故障監測技術,通過三類監測點的插入可以有效地監測內核中動態內存分配和資源競爭相關的故障,并通過錯誤注入實驗驗證了該技術的可行性,實現的故障監測器可以在較低系統負載的條件下對注入的故障進行有效的監測,且故障誤報率很低,監測延時較已有的基于時間和系統性能指標的監測技術明顯降低。
[1]Barbosa R.Layered fault tolerance for distributed embedded systems[M].[S.l.]:Chalmers University of Technology,2008.
[2]Schneider C,Barker A,Dobson S.A survey of self-healing systems frameworks[J].Software:Practice and Experience,2014.
[3]Hamann P S,Perry R L.Compensation recommendations,US patent 20,140,032,382[P].2014.
[4]Asghari S A,Kaynak O,Taheri H.An investigation into soft error detection efficiency at operating system level[J].The Scientific World Journal,2014.
[5]Abaffy J,Krajcovic T.Software support for multiple hardware watchdog timers in the linux OS[J].Applied Electronics,2010:17-19.
[6]David F M,Campbell R H.Building a self-healing operating system[C]//Third IEEE International Symposium on Dependable,Autonomic and Secure Computing,2007:3-10.
[7]Zhu Y,Li Y,Xue J,et al.What is system hang and how to handle it[C]//Software Reliability Engineering(ISSRE).
[8]Abaffy J,Kraj?ovi? T.Multiple software watchdog timers in the linux OS[M]//Emerging Trends in Computing,Informatics,Systems Sciences,and Engineering.[S.l.]:Springer,2013:759-765.
[9]Palix N,Thomas G,Saha S,et al.Faults in Linux:ten years later[C]//ACM SIGARCH Computer Architecture News,ACM,2011:305-318.
[10]Chou A,Yang J,Chelf B,et al.An empirical study of operating systems errors[Z].ACM,2001.
[11]Lisong L,Peter P,Tschudin S,et al.Oops!What about a Million Kernel Oopses?RT-0436[R].2013.
[12]Deshpande B D.System and methods for self-healing from operating system faults in kernel/supervisory mode,US Patent 20,140,032,962[P].2014.
[13]Saha S,Lozi J P,Thomas G,et al.Hector:detecting resource-release omission faults in error-handling code for systems software[C]//43rd Annual IEEE/IFIP International Conference on Dependable Systems and Networks.IEEE,2013:1-12.
[14]Kheradmand A,Kasikci B,Candea G.Lockout:efficient testing for deadlock bugs[R].2014.
[15]Bovenzi A,Cinque M,Cotroneo D,et al.OS-level hang detection in complex software systems[J].International Journal of Critical Computer-Based Systems,2011,2:352-377.
[16]Cotroneo D,Natella R,Russo S.Assessment and improvement of hang detection in the Linux operating system[C]//Reliable Distributed Systems,2009:288-294.