簡介
陷阱
計算機有兩種運行模式:用戶態, 核心態。 其中作業系統運行在核心態,在核心態中,作業系統具有對所有硬體的完全訪問許可權,可以使機器運行任何指令;相反,用戶程式運行在用戶態,在用戶態下,軟體只能使用少數指令,它們並不具備直接訪問硬體的許可權。這就出現了問題,假如軟體需要訪問硬體或者需要調用核心中的函式該怎么辦呢,這就是陷阱的作用了。陷阱指令可以使執行流程從用戶態陷入核心(這也就是為什麼叫做陷阱,而不是捕獵的陷阱)並把控制權轉移給作業系統,使得用戶程式可以調用核心函式和使用硬體從而獲得作業系統所提供的服務,比如用視頻軟體放一個電影,視頻軟體就發出陷阱使用顯示器和音效卡從而訪問硬體。
作業系統有很多系統調用接口供用程式調用。陷阱的發生時間是固定的,比如第一次用視頻軟體時,在載入視頻時軟體會向作業系統傳送陷阱指令,第二次播放時,軟體仍然會在同樣的時刻傳送陷阱指令。這一點是和中斷的明顯的差別之一。下面介紹中斷。
中斷
中斷是由外部事件導致並且它發生的時間是不可預測的,這一點和陷阱不同。外部事件主要是指時鐘中斷,硬體中斷等。由於CPU一次只能運行一條指令,所以在一個時刻只能有一個程式運行,但我們感覺在我們的計算機中明明可以同時運行很多程式啊,這是由於CPU在多個進程之間快速切換所導致的偽並行。如果某一個程式運行了足夠長用完了分配給它的時間片,CPU決定切換到另一個進程運行,就會產生一個時鐘中斷,切換到下一個進程運行。
硬體中斷顧名思義就是由硬體引起的中斷,比如一個程式需要用戶輸入一個數據,但用戶一直沒有輸入,作業系統決定是一直等待用戶輸入還是轉而運行別的進程,一般情況是轉而運行別的進程,如果用戶的輸入到來了,那么鍵盤驅動器會產生一個中斷通知作業系統,作業系統保存正在運行的程式的狀態,從而切換到原來的進程處理到來的數據。
所以中斷髮生是隨機的且主要作用是完成進程間切換,從而支持CPU和設備之間的並行。
中斷和異常的另一個重要差別是,CPU處理中斷的過程中會禁止中斷,不接受新的中斷直到此次中斷處理結束。而陷阱的發生並不禁止中斷,可以接受新的中斷。
異常
異常就是程式執行過程中的異常行為。比如除零異常,緩衝區溢出異常等。不同的作業系統定義了不同種類和數量的異常並且每個異常都有一個唯一的異常號,異常會擾亂程式的正常執行流程,所以異常是在CPU執行指令時本身出現的問題,比如除數為零而出現的除零異常。異常的產生表示程式設計不合理,所以在編程的時候要儘量避免異常的產生。
異常陷阱的基本概念
中斷是指計算機在執行期間,系統內發生任何非尋常的或非預期的急需處理事件,使得CPU暫時中斷當前正在執行的程式而轉去執行相應的事件處理程式,待處理完畢後又返回原來被中斷處繼續執行或調度新的進程執行的過程。引起中斷髮生的事件被稱為中斷源。中斷源向CPU發出的請求中斷處理信號稱為中斷請求,而CPU收到中斷請求後轉到相應的事件處理程式稱為中斷回響。
在有些情況下,儘管產生了中斷源和發出了中斷請求,但CPU內部的處理器狀態字PSW的中斷允許位已被清除,從而不允許CPU回響中斷。這種情況稱為禁止中斷。CPU禁止中斷後只有等到PSW的中斷允許位被重新設定後才能接收中斷。禁止中斷也稱為關中斷,PSW的中斷允許位的設定也被稱為開中斷。開中斷和關中斷是為了保證某段程式執行的原子性。
還有一個比較常用的概念是中斷禁止。中斷禁止是指在中斷請求產生之後,系統有選擇地封鎖一部分中斷而允許另一部分中斷仍能得到回響。不過,有些中斷請求是不能禁止甚至不能禁止的,也就是說,這些中斷具有最高優先權,只要這些中斷請求一旦提出,CPU必須立即回響。例如,電源掉電事件所引起的中斷就是不可禁止和不可禁止的。
分類與優先權
根據系統對中斷處理的需要,作業系統一般對中斷進行分類並對不同的中斷賦予不同的處理優先權,以便在不同的中斷同時發生時,按輕重緩急進行處理。
根據中斷源產生的條件,可把中斷分為外中斷和內中斷。外中斷是指來自處理器和記憶體外部的中斷,包括I/0設備發出的I/O中斷、外部信號中斷(例如用戶鍵人ESC鍵)。各種定時器引起的時鐘中斷以及調試程式中設定的斷點等引起的調試中斷等。外中斷在狹義上一般被稱為中斷。
內中斷主要指在處理器和記憶體內部產生的中斷。內中斷一般稱為陷阱(trap)或異常。它包括程式運算引起的各種錯誤,如地址非法、校驗錯、頁面失效、存取訪問控制錯、算術操作溢出、數據格式非法、除數為零、非法指令、用戶程式執行特權指令、分時系統中的時間片中斷以及從用戶態到核心態的切換等都是陷阱的例子。
為了按中斷源的輕重緩急處理回響中斷,作業系統為不同的中斷賦予不同的優先權。例如在UNIX系統中,外中斷和陷阱的優先權共分為8級。為了禁止中斷或禁止中斷,CPU的處理器狀態字PSW中也設有相應的優先權。如果中斷源的優先權高於PSW的優先權,則CPU回響該中斷源的請求;反之,CPU禁止該中斷源的中斷請求。
各中斷源的優先權在系統設計時給定,在系統運行時是固定的。而處理器的優先權則根據執行情況由系統程式動態設定。除了在優先權的設定方面有區別之外,中斷和陷阱還有如下主要區別:
陷阱通常由處理器正在執行的現行指令引起,而中斷則是由與現行指令無關的中斷源引起的。陷阱處理程式提供的服務為當前進程所用,而中斷處理程式提供的服務則不是為了當前進程的。中斷是由硬體引起的,而異常是由軟體引起的;中斷是異步的,而異常是同步的。
CPU執行完一條指令之後,下一條指令開始之前回響中斷,而在一條指令執行中也可以回響陷阱。例如執行指令非法時,儘管被執行的非法指令不能執行結束,但CPU仍可對其進行處理。
異常陷阱類指令
BKPT斷點
格式:BKPT
操作:
(SSP)一(SP)一6
((SP))一(PC)
((SSP))一(PSW)
(PSW)+-代碼存貯器(斷點向量)
(PC.15一o)一代碼存貯器(斷點向量)
說明:引起一個斷點陷阱。它類似於立即中斷,使用某一向量調用一個將在系統方式下被執行的代碼塊。該指令用於仿真器系統,以提供執行硬體斷點的一種簡單方法。
對於一個在所有條件下均適合工作的斷點,其指令長度必須不大於處理器中最短的其它指令。這種情況下,為單位元組NOP。這種要求是困為斷點可能被插入後隨其它指令的NOP位置,該指令為轉移或者不通過斷點執行。若斷點指令長於NOP。它在執行指令序列時將與下一條指令發生衝突。
斷點指令操作碼特定為全1(FF)。這樣,未編程的EPROM代碼存貯器將包括斷點。類似的,NOP指令操作碼為全0,以便兩個“空白”碼說明無害指令。
長度:無
影響標誌:無
位元組數:1
周期數:23/19(PZ)
RESET軟體復位
格式:RESET
操作:(PC)<一向量(0) ,
(PSW)<一向量(b)
(SFR)<一復位數值
說明:只要外部硬體發生復位,晶片將藉助異常嚴格復位,其不對配置輸入端(例如:EA,BUSW等)採樣。當執行RESET指令時,晶片內部復位但不產生外部RESET脈衝,RESET脈衝上升沿期間被鎖存的以上輸入端狀態,不影響晶片配置。
影響標誌:整個PSW被置為復位向量中指定的數值。
位元組數:2
周期數:19
TRAP軟體陷阱
格式:TRAP#data4
操作:(PC)一(PC)+2
(SSP)一(SSP)一6
((SSP))一(PC)
((SSP))一(PSW)
(Psw)一代碼存貯器(陷阱向量(#data4))
(PC.15一o)一代碼存貯器(陷阱向量(#data4))
(PC.23—16)一0:(PC.0)一0
說明:引起指定的軟體陷阱。引發的子程式由分支至指定的向量表輸入點決定。RETI指令被用於陷阱子程式完成後的恢復執行。陷阱的作用類似於立即中斷,使用向量調用一些將在系統方式下執行的代碼段之一。它可用於獲得套用代碼的系統服務,例如修改數據段暫存器。有關內容在中斷和異常中有詳細描述。
註:異常處理子程式的地址必須是字。因為在轉向服務子程式前PC被強迫為一偶地址。
影響標誌:無 ‘
位元組數:2 、
周期數;23/19(PZ)
異常陷阱類指令一覽表
助記符 | 功能 | 位元組數 | 時鐘數 |
BKPT | 引起執行斷點陷阱 | 1 | 23/19(PZ) |
RESET | 與外部復位相同,引起一次硬體復位 | 2 | 8 |
TRAP#data | 引起執行16種硬體陷阱之一 | 2 | 23/19(Pz) |
異常陷阱處理機制
包括資料庫連線失敗、IO錯誤、數據溢出、數組下標越界等,鑒於此,提供異常處理機制。允許開發者捕獲程式運行時可能的異常。
異常類Exception
.NET可以自動捕捉程式中所有可能的錯誤,並通過Exception類返回。簡單地說,Exception類可以表示程式執行期間發生的錯誤。其常用的屬性可以幫助標記異常的代碼位置、類型、幫助檔案和原因。Exception的常用屬性如表所示。
屬性 | 說明 |
Data | 獲取一個提供用戶定義的其他異常信息的鍵/值對的集合。 |
HelpLink | 獲取或設定指向此異常所關聯幫助檔案的連結。 |
InnerException | 獲取導致當前異常的Exception實例。 |
Message | 獲取描述當前異常的訊息 |
Source | 獲取或設定導致錯誤的應用程式或對象的名稱。 |
StackTrace | 獲取當前異常發生時調用堆疊上的幀的字元串的表達形式。 |
TargetSite | 獲取引發當前異常的方法。 |
使用try-catch處理異常
Exception類必須結合try-catch-finally代碼塊使用程式將自動轉向catch{...}代碼塊。並執行其中的內容。無論是否出現異常,程式都會執行finally{...}中的代碼。
語法格式為
try
{
語句序列
}
catch(異常類型 標記符)
{
異常處理
}
finally
{
語句序列
)