重學計算機組成原理(十二) - 異常和中斷

      網友投稿 1040 2022-05-28

      1 概覽

      完好的程序都滿足以下特征

      自動運行

      我們的程序和指令都是一條條順序執行,不需要通過鍵盤或者網絡給這個程序任何輸入

      正常運行

      沒有遇到計算溢出之類的程序錯誤。

      不過,現實的軟件世界可沒有這么簡單

      程序不僅是簡單的執行指令,更多的還需要和外部的輸入輸出打交道

      程序在執行過程中,還會遇到各種異常情況,比如除以0、 溢出,甚至我們自己也可以讓程序拋出異常。

      遇到這些情況,計算機是怎么運轉的呢,也就是說,計算機究竟是如何處理異常的

      2 異常:硬件、系統和應用的組合拳

      2.1 軟件 還是 硬件 異常?

      一提到異常 (Exception),可能你的第一反應就是Java中的Exception。 不過我們今天講的,并不是這些軟件開發過程中遇到的“軟件異常”

      而是和硬件、系統相關 的“硬件異常”。

      當然,“軟件異常”和“硬件異常”并不是業界使用的專有名詞,只是我為了方便給你說明,和Java中軟件拋出的Exception進行的人為區分,你明白這個意思就好。

      盡管,這里我把這些硬件和系統相關的異常,叫作“硬件異常”。但是,實際上,這些異常,既有來自硬件的,也有來自軟件層面的。

      比如,我們在

      硬件層面

      當加法器進行兩個數相加的時候,會遇到算術溢出

      或者,你在玩游戲的時候,按下鍵盤發送了一個信號給到CPU,CPU要去執行一個現有流程之外的指令,這也是 一個“異常”

      同樣,來自

      軟件層面

      比如我們的程序進行系統調用,發起一個讀文件的請求。這樣應用程序向系統調用發起請求的情況,一樣是通過“異常”來實現的。

      2.2 異常的一生

      異常, 其實是一個硬件和軟件組合到一起的處理過程。

      異常的前半生

      異常的發生和捕捉,在硬件層面完成

      異常的后半生

      異常的處理,其實是由軟件來完成的!

      2.3 異常代碼

      計算機會為每一種可能會發生的異常,分配一個異常代碼(Exception Number)

      異常代碼也叫作中斷向量(Interrupt Vector)。

      異常發生的時候,通常是CPU檢測到了一個特殊的信號。

      比如

      你按下鍵盤上的按鍵,輸入設備就會給CPU發一個信號

      正在執行的指令發生了加法溢出,同樣,我們可以有一個進位溢出的信號

      這些信號呢,在組成原理,一般叫發生了一個事件(Event)

      CPU在檢測到事件的時候,其實也就拿到了對應的異常代碼。

      重學計算機組成原理(十二) - 異常和中斷

      這些異常代碼里

      I/O發出的信號的異常代碼,是由操作系統來分配的,也就是由軟件來設定的

      像加法溢出這樣的異常代碼,則是由CPU預先分配好的,也就是由硬件來分配的. 這又是另一個軟件和硬件共同組合來處理異常的過程

      拿到異常代碼之后,CPU就會觸發異常處理的流程

      計算機在內存里,會保留一個異常表 (Exception Table)。

      也叫中斷向量表(Interrupt Vector Table),好和上面的中斷向量對應起來。

      這個異常表有點兒像我們在之前的GOT表,存放的是不同的異常代碼對應的異常處理程序(Exception Handler)所在的地址

      2.4 異常處理程序流程

      我們的CPU在拿到了異常碼后

      首先, 把當前的程序執行的現場,保存到程序棧

      然后, 根據異常碼查詢,找到對應的異常處理程序

      最后, 把后續指令執行的指揮權,交給這個異常處理程序

      這樣“檢測異常 => 拿到異常碼 => 再根據異常碼進行查表處理”的模式,在日常開發的過程中是很常 見的。

      Created with Rapha?l 2.2.0

      開始

      檢測異常

      拿到異常碼

      再根據異常碼進行查表處理

      結束

      比如說

      Web或者App開發

      通常都是前后端分離的

      前端應用,會向后端發起HTTP請求

      當后端遇到了異常,通常會給到前端一個對應的錯誤代碼

      前端的應用根據這個錯誤代碼,

      在應用層面去進行錯誤處理

      在不能處理的時候,它會根據錯誤代碼向用戶顯示錯誤信息。

      可以設定ExceptionHandler,來處理線程執行中的異常情況

      public class LastChanceHandler implements Thread.UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { // do something here - log to file and upload to // server/close resources/delete files... } } Thread.setDefaultUncaughtExceptionHandler(new LastChanceHandler());

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      可以指定一個異常處理程序。

      對于各個線程在執行任務出現的異常情況,我們是通過異常處理程序進行處理,而不是在實際的任務代碼里處理。

      這樣,我們就把業務處理代碼就和異常處理代碼的流程分開了。

      3 異常的分類

      異常可以由硬件觸發,也可以由軟件觸發

      3.1 中斷(Interrupt)

      顧名思義,就是程序在執行到一半的時候,被打斷了。這個打斷執行的信號,來自于CPU外部的I/O設備。

      你在鍵盤上按下一個按鍵,就會對應觸發一個 相應的信號到達CPU里面。CPU里面某個開關的值發生了變化,也就觸發了一個中斷類型的異常。

      3.2 陷阱(Trap)

      程序員“故意“主動觸發的異常。就好像你在程序里面打了一個斷點,這個斷點就是設下的一個"陷阱"。

      當程序的指令執行到這個位置的時候,就掉到了這個陷阱當中。然后,對應的異常處理程序就會來處理這個"陷阱"當中的獵物。

      最常見的一類陷阱,應用程序調用系統調用的時候,也就是從用戶態切換到內核態的時候。

      可以用Linux下的time指令,去查看一個程序運行實際花費的時間,里面有在用戶態花費的時間(user time),也有在內核態發生的時間 (system time)。

      應用程序通過系統調用去讀取文件、創建進程,其實也是通過觸發一次陷阱來進行的。這是因為用戶態的應用程序沒有權限來做這些事情,需要把對應的流程轉交給有權限的異常處理程序來進行。

      3.3 故障(Fault)

      陷阱是我們開發程序的時候刻意觸發的異常,而故障通常不是。

      比如,我們在程序執行的過程中,進行加法計算發生了溢出,其實就是故障類型的異常。

      這個異常不是我們在開發的時候計劃內的,也一樣需要有對應的異常處理程序去處理。

      故障和陷阱、中斷的重要區別

      故障在異常程序處理完成之后,仍然回來處理當前的指 令,而不是去執行程序中的下一條指令。

      因為當前的指令因為故障的原因并沒有成功執行完成。

      3.4 中止(Abort)

      與其說這是一種異常類型,不如說這是故障的一種特殊情況。 當CPU遇到了故障,但是恢復不過來的時候,程序就不得不中止了。

      3.5小結

      中斷異常的信號來自系統外部,而不是在程序自己執行的過程中,所以我們稱之為“異步”類型的異常。

      而陷阱、故障以及中止類型的異常,是在程序執行的過程中發生的,所 以我們稱之為“同步“類型的異常。

      在處理異常的過程當中,無論是異步的中斷,還是同步的陷阱和故障,我們都是采用同一套處理流程,也就是上面所說的,“保存現場、異常代碼查詢、異常處理程序調用“。

      而中止類型的異常,其實是在故障類型異常的一種特殊情況。當故障發生,但是我們發現沒有異常處理程序能夠處理這種異常的情況下,程序就不得不進入中止狀態,也就是最終會退出當前的程序執行。

      4 異常的處理:上下文切換

      在實際的異常處理程序執行之前,CPU需要去做一次“保存現場”的操作。這個保存現場的操作, 和函數調用的過程非常相似。

      切換到異常處理程序,就好像是去調用一個異常處理函數。指令的控制權被切換到了另外一個"函數",所以我們自然要把當前正在執行的指令去壓棧。

      這樣才能在異常處理程序執行完后,重新回到當前的指令繼續往下執行。

      不過,切換到異常處理程序,比起函數調用,還是要更復雜一些。原因有下面幾點

      異常情況往往發生在程序正常執行的預期之外,比如中斷、故障發生的時候。所以,除了本來程序壓棧要做的事情之外,還需要把CPU內當前運行程序用到的所有寄存器, 都放到棧里面。最典型的就是條件碼寄存器里面的內容

      像陷阱這樣的異常,涉及程序指令在用戶態和內核態之間的切換。對應壓棧的時候,對應的數據是壓到內核棧里,而不是程序棧里。

      像故障這樣的異常,在異常處理程序執行完成之后。從棧里返回出來,繼續執行的不是順序的下一條指令,而是故障發生的當前指令。因為當前指令因為故障沒有正常執行成功,必須重新去執行一次。

      所以,對于異常這樣的處理流程,不像是順序執行的指令間的函數調用關系。而是更像兩個不同的獨立進程之間在CPU層面的切換,所以這個過程我們稱之為上下文切換(Context Switch)。

      5 總結

      計算機里的“異常”處理流程。這里的異常可以分成中斷、陷阱、故障、中止 這樣四種情況。這四種異常,分別對應著I/O設備的輸入、程序主動觸發的狀態切換、異常情況下的程序出錯以及出錯之后無可挽回的退出程序。

      當CPU遭遇了異常的時候,計算機就需要有相應的應對措施。CPU會通過“查表法”來解決這個問 題。在硬件層面和操作系統層面,各自定義了所有CPU可能會遇到的異常代碼,并且通過這個異 常代碼,在異常表里面查詢相應的異常處理程序。在捕捉異常的時候,我們的硬件CPU在進行相 應的操作,而在處理異常層面,則是由作為軟件的異常處理程序進行相應的操作。

      而在實際處理異常之前,計算機需要先去做一個“保留現場”的操作。有了這個操作,我們才能在異常處理完成之后,重新回到之前執行的指令序列里面來。這個保留現場的操作,和我們之前講 解指令的函數調用很像。但是,因為“異常”和函數調用有一個很大的不同,那就是它的發生時間。函數調用的壓棧操作我們在寫程序的時候完全能夠知道,而“異常”發生的時間卻很不確定。 所以,“異常”發生的時候,我們稱之為發生了一次“上下文切換”(Context Switch)。這個時 候,除了普通需要壓棧的數據外,計算機還需要把所有寄存器信息都存儲到棧里面去。

      推薦閱讀

      關于異常和中斷,《深入理解計算機系統》的第8章“異常控制流”部分,有非常深入和充分的講解,推薦你認真閱讀一下。

      再續中斷分類

      軟中斷和硬中斷

      硬中斷

      由硬件發出或產生的中斷稱為硬中斷,按硬中斷事件的來源和實現手段可將中斷劃分為外中斷和內中斷:

      外中斷

      又稱為中斷或異步中斷,是指來自處理器以外的中斷信號,包括時鐘中斷、鍵盤中斷、外部設備中斷等。外中斷又分為可屏蔽中斷和不可屏蔽中斷,各個中斷具有不同的優先級,表示事件的緊急程度,在處理高一級中斷時,往往會部分或全部屏蔽低等級中斷。

      內中斷

      又稱為異常或同步中斷(產生時必須考慮與處理器時鐘同步),是指 來自處理器內部的中斷信號,通常是由于程序執行過程中,發現與當前指令關聯的、不正常的或錯誤的事件。內中斷可以細分為:

      訪管中斷,由執行系統調用而引起的

      硬件故障中斷,如電源失效、總線超時等

      程序性中斷,如非法操作、地址越界、除數為0和浮點溢出等。

      軟中斷

      是一條CPU指令,用以自陷一個中斷。由于 軟中斷指令通常要運行一個切換CPU至內核態(Kernel Mode/Ring 0)的子例程,它常被用作實現系統調用(System call)。

      處理器通常含有一個內部中斷屏蔽位,并允許通過軟件來設定。一旦被設定,所有外部中斷都將被系統忽略。這個屏蔽位的訪問速度顯然快于中斷控制器上的中斷屏蔽寄存器,因此可提供更快速地中斷屏蔽控制。

      中斷風暴(interrupt storm)

      中斷盡管可以提高計算機處理性能,但 過于密集的中斷請求/響應反而會影響系統性能。這類情形被稱作

      參考

      https://www.cnblogs.com/luoahong/p/11425628.html#top

      深入理解計算機系統(第三版)

      Java 任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:MySQL系列之二進制日志Binlog學習筆記
      下一篇:【音頻處理】Adobe Audition 快捷鍵設置
      相關文章
      亚洲国产精品免费观看 | 久久久久亚洲AV片无码| 亚洲成AV人影片在线观看| 亚洲无限乱码一二三四区| 久久久久久久久亚洲| 国产亚洲综合久久系列| 美腿丝袜亚洲综合| 亚洲自偷自偷图片| 中文字幕专区在线亚洲| 亚洲色成人网站WWW永久| 亚洲亚洲人成综合网络| 国产亚洲精品xxx| 亚洲成AV人片在线观看无| 亚洲Av无码精品色午夜| 亚洲国产二区三区久久| 亚洲日韩区在线电影| 亚洲成AV人片在线观看无码 | 亚洲人成网站色7799| 亚洲愉拍一区二区三区| 亚洲国产精华液2020| 国产亚洲精品91| 亚洲午夜激情视频| 亚洲日韩精品一区二区三区 | 亚洲va久久久噜噜噜久久天堂| 国产亚洲人成网站在线观看不卡| 亚洲精品国产精品乱码视色 | 国产精品亚洲小说专区| 亚洲国产精品人人做人人爽| 亚洲国产精品一区二区三区久久 | 精品国产亚洲男女在线线电影 | 亚洲午夜精品一区二区麻豆| 国产成人精品日本亚洲语音 | 亚洲男女内射在线播放| 日韩亚洲变态另类中文| 亚洲爆乳无码一区二区三区| 久久亚洲AV成人无码电影| 亚洲三级视频在线观看| 亚洲欧美综合精品成人导航| 国产成人亚洲精品蜜芽影院| 亚洲宅男天堂在线观看无病毒| 久久精品国产亚洲av麻|