260 likes | 446 Views
軟體工程. 第 20 章 關鍵系統開發. 學習目標. 瞭解避免錯誤與容錯技術對於開發可信賴系統的貢獻 知道在可信賴軟體的程序中所包含活動的特性 瞭解要達到避免錯誤的程式設計技巧 瞭解實作容錯系統的階段,以及在容錯架構中要達成多樣性和重複性所使用的方式. 要開發可信賴的軟體,有 3 種可相互搭配的方法:. 避免錯誤( fault avoidance ):系統的設計與實作程序,應該使用能夠避免程式設計錯誤以及減少程式中出現其他錯誤的軟體開發方法。 偵測錯誤( fault detection ):設計驗證與確認程序,目的是在系統開始部署正式上線前發現錯誤並移除錯誤。
E N D
軟體工程 第20章 關鍵系統開發
學習目標 • 瞭解避免錯誤與容錯技術對於開發可信賴系統的貢獻 • 知道在可信賴軟體的程序中所包含活動的特性 • 瞭解要達到避免錯誤的程式設計技巧 • 瞭解實作容錯系統的階段,以及在容錯架構中要達成多樣性和重複性所使用的方式
要開發可信賴的軟體,有3種可相互搭配的方法:要開發可信賴的軟體,有3種可相互搭配的方法: • 避免錯誤(fault avoidance):系統的設計與實作程序,應該使用能夠避免程式設計錯誤以及減少程式中出現其他錯誤的軟體開發方法。 • 偵測錯誤(fault detection):設計驗證與確認程序,目的是在系統開始部署正式上線前發現錯誤並移除錯誤。 • 容忍錯誤(fault tolerance,簡稱容錯):系統應該設計成在執行期間能夠偵測與管理系統的錯誤或非預期行為,讓系統不會發生故障。
20.1可信賴的程序 • 可信賴的程序(dependable process)是指針對錯誤避免和錯誤偵測所採用的各種程序。 • 可信賴的程序擁有完善定義(well defined)且可重複執行(repeatable),而且包含一系列的驗證與確認活動。 • 有完善定義的程序是指有經過標準化和文件記錄的程序,可重複執行的程序則是指程序不會因不同人而有不同的詮釋和判斷。 • 無論參與程序的人為何,這些程序都應該能夠成功的完成。
針對錯誤避免和錯誤偵測的程序活動包括: • 需求檢查(requirements inspections):這是為了要找出系統規格的問題。 • 需求管理(requirements management):在已交付系統中有很多錯誤,是因為沒有確實的將需求變更包含到系統的設計與實作中所導致。 • 模型檢查(model checking):模型檢查的活動包括利用CASE工具自動分析系統的模型,以確保內外的一致性。內部的一致性(internal consistency)是指同一個模型內是一致的;而外部的一致性(external consistency)則是指同一個系統的不同模型也必須一致(如狀態模型與物件模型)。 • 設計與程式碼檢查(design and code inspections):設計與程式碼的檢查通常是依據常見錯誤清單為主,必須在系統測試之前發現並且移除這些錯誤。 • 靜態分析(static analysis):靜態分析是一個自動分析程式的技巧。此時程式會被詳細的進行分析,以找出可能的錯誤情況。測試規劃與管理(test planning and management):要針對系統設計一套完整的測試,而且測試程序本身也應該小心的管理,以確保系統測試和系統需求與設計之間的測試,能夠完整的被涵蓋與追蹤。
20.2可信賴的程式設計 • 可信賴的程式設計(dependable programming)是指使用有助於錯誤避免和容錯的程式設計構件和技術。 • 程式中會出現錯誤,是因為程式設計人員犯錯的關係。雖然有些錯誤是因為誤解規格所導致,但是還是有些是因為程式過於複雜,或者是採用容易出錯的方式來設計。因此,為了提高可信賴度,設計應該儘量簡單,保護資訊不被未經授權的存取,並減少使用不安全的程式設計構件。 • 有容錯功能的程式設計技術要能夠有作用,必須先區分錯誤(fault)和故障。所謂的故障(failure)對於系統使用者而言是可以觀察到的東西,而錯誤(fault)則是一種系統內部的特性。
受保護的資訊 • 若使用資訊隱藏(information hiding)技術,被隱藏的資料就不會受到無權存取的程式元件所損毀。如果介面保持相同,就可以在不影響系統其他元件的情況下變更資料的表示方式。 • 保護資訊在Java語言中比在其他舊的程式語言(如C或Pascal)中容易。因為這些語言沒有像物件類別這樣的封裝構件(construct),所以資料結構的實作細節無法受到保護。 • 使用物件導向語言來撰寫程式是非常好的做法,它會提供方法來存取和更新屬性值,而不是讓其他物件直接存取這些屬性。這表示屬性的表示方式可以直接修改,不必考慮其他物件要如何使用這個屬性。
安全的程式設計 • 程式中的錯誤以及所導致的許多程式故障,通常都是人為錯誤的結果。 • 程式設計人員可能會因為沒有追蹤所有狀態變數之間的關係而造成一些錯誤,也可能會寫出一些產生非預期行為和改變系統狀態的程式敘述。
容易產生錯誤的構件如下: • 浮點數:浮點數原本就不是非常精確,所以浮點數在進行比較運算時,可能會因為表示方式的不同而發生錯誤。 • 指標:指標是一種低階的構件,它儲存能直接參考到機器記憶體區域的位址(address)。因為指標允許使用「別名」(alias)技術,而且使用指標比較不容易進行陣列以及其他結構的邊界檢查,所以如果錯用指標將造成毀滅性的危險。 • 動態記憶體配置:程式記憶體是在執行期間配置的,而不是在編譯期間配置。這樣做的危險是記憶體可能一直沒有釋回,而導致用光系統可用的記憶體。 • 平行處理(parallelism):平行處理也是很危險的,因為很難預測平行的行程之間在時序上的互動情形。 • 遞迴(recursion):遞迴是某個程序或方法呼叫自己的一種情況,或是先呼叫其他程序,然後再呼叫自己的情況。使用遞迴可以寫出非常簡潔的程式,但是遞迴程式的邏輯卻很難追蹤。 • 插斷:插斷是指將控制權強迫轉移到另外一段程式碼,而不管目前正在執行的程式碼。這個動作的危險在於:插斷可能會終止了某個非常關鍵的動作。 • 繼承:物件導向程式設計中的繼承功能有個問題,這會造成同一個物件的相關程式碼不會全都放在同一地方,這使得物件的行為不容易理解,因此也更容易產生程式設計的錯誤。此外,若繼承與動態繫結(dynamic binding)動作合併使用,可能會在執行期間引起時序上的問題。 • 別名(aliasing):這項技術可以使用不同名稱來參考程式中的同一個實體。 • 無邊界的陣列(unbounded array):例如使用C語言的陣列是存取記憶體最簡單的方式,而且還可以指派值給超過陣列邊界的記憶體位置。 • 預設輸入值處理:有些系統會對輸入提供預設值,而不顧目前真正給系統的輸入值。
例外處理 • 在程式執行期間,若有某些錯誤或是非預期事件發生時,稱為例外狀況(exception)。 • 這些例外狀況可能是由硬體或軟體的情況所引起的,例如系統電源發生故障、嘗試存取不存在的資料項目或是數值溢位等。 • 當例外狀況發生時,系統要能夠處理。系統可以讓程式本身來處理,或是將控制權轉移給系統例外處理(exception handling)機制來處理。 • 通常系統的例外管理機制只是報告有錯誤並停止執行而已。因此,為了確保程式的例外狀況不會引起系統故障,應該要針對每個可能的例外狀況,定義一個例外處理函式(exception handler),確保每種例外狀況都有明確的進行處理。
20.3容錯 • 容錯系統(fault-tolerant system)是指系統發生某些錯誤之後,還能夠持續運作的系統。 • 容錯機制的目的是要確保系統錯誤不會導致系統故障。 • 當系統故障可能會引起災難事件,或是當系統停止運作將引起重大經濟損失的情況下,都需要容錯機制。
容錯包括下列4個層面: • 錯誤偵測(fault detection):系統必須能夠偵測出會導致系統故障的錯誤。通常這牽涉到檢查系統狀態是否一致。 • 損害評估(damage assessment):必須偵測出已經受到錯誤所影響的系統狀態部份。 • 錯誤回復(fault recovery):系統必須能夠回復到已知的「安全」狀態。這可以利用修正已損壞的狀態(向前錯誤回復),或是將系統回復到已知的「安全」狀態(向後錯誤回復)來達成。 • 錯誤修復(fault repair):修改系統使錯誤不再復發。在許多情況下,軟體錯誤都只是短暫的狀態,這些錯誤通常都是某些系統輸入值的特殊組合。錯誤回復之後並不需要進行修復,而且能夠立即恢復正常處理。
錯誤偵測與損害評估 • 容錯的第一步是偵測出已經發生的錯誤(錯誤的系統狀態),或者是除非立刻採取行動否則即將發生的錯誤。 • 當定義的狀態限制只會套用在個別的狀態變數時,可以採用預防性錯誤偵測方式。
錯誤偵測有下列2種類型: • 預防性錯誤偵測(preventative fault detection):在這種情況下,錯誤偵測機制會在狀態改變被提交(committed)之前啟動。如果偵測出可能出錯的狀態,那麼就不變更此狀態。 • 回溯性錯誤偵測(retrospective fault detection):在這種情況下,錯誤偵測機制會在系統狀態已經改變後才啟動,以檢查是否有錯誤發生。如果發現錯誤,便會發出例外情況的訊號,並且使用修復機制從錯誤中回復。
錯誤回復和修復 • 錯誤回復(fault recovery)是一個修改系統狀態空間的行程,以便讓錯誤的影響消失或降低。 • 有些系統雖然效能會降級,但仍然能夠繼續運作。向前回復(forward recovery)會嘗試修正被損壞的系統狀態,建立想要的狀態;而向後回復(backward recovery)則會將系統狀態還原(restore)到已知「正確的」狀態。 • 向前錯誤回復只有在狀態資訊中內建有重複資料才有用。
下列這2種一般情況都可以應用向前錯誤回復技術: • 編碼資料被損毀:使用為資料加入重複性的編碼技術,使得能修正與偵測錯誤。 • 鏈結的結構被損毀:如果資料結構中有包含向前與向後的指標,而且結構中還有足夠的指標未損壞,就可以重建此結構。這個技巧通常是用來修復檔案系統和資料庫。
20.4容錯架構 • 在許多系統中要實作軟體的容錯機制,可以經由在軟體中加上明確的檢查和回復動作來達成。這稱作防禦式程式設計(defensive programming)。 • 但是,它沒有辦法有效處理在硬體和軟體互動之間所產生的系統錯誤。另外,對需求的誤解也可能會讓系統的程式碼和相關的防禦措施不正確。 • 建立具有容錯功能的硬體是多年來的需求。其中最常用的硬體容錯技術,是以「三重模組備援」(triplemodular redundancy, TMR)的觀念為基礎。
如果系統的可用性與可靠度需求必須要有硬體容錯功能,那麼可能也需要軟體的容錯。提供軟體容錯機制有兩種方法。如果系統的可用性與可靠度需求必須要有硬體容錯功能,那麼可能也需要軟體的容錯。提供軟體容錯機制有兩種方法。 • N版本程式設計(N-version programming):這種方法同時至少需要3種不同的版本,而在同一個故障事件必須有2個版本有一致的結果。這是軟體容錯最普遍的方式,它已經被應用在鐵路號誌系統、飛機系統及反應爐保護系統上。 • 回復區塊(recovery block):這個方法是在每一個程式元件中包含一個測試,用來檢查該元件是否成功的執行完成。 • 這兩個方法都是從具有備援元件(或是備援系統)的硬體模型衍生而來,一旦發生錯誤便將出錯的元件撤離服務狀態。