今天csapp學習了異常的相關概念。
程式內的執行流切換無非兩種,一種是分支和跳轉;另一種是呼叫和返回。但是為了響應某些的事件,例如鍵盤輸入和ctrl+c終止程式;以及程式的缺頁錯誤或者段錯誤,就需要另一種執行流切換的方式。這種特殊處理叫做異常。
異常是將事件交給核心處理的過程,實現的層級從低到高包含異常、程序切換、訊號和非本地跳轉。
首先異常的分類。異常事件按照是否出現於當前執行的程式內來區分同步異常和非同步異常。同步異常是程式內的操作導致的,包括內陷、故障和錯誤。內陷是程式故意操作的,例如系統呼叫以及中斷。而故障和錯誤則是無意的。故障出現後,核心可能恢復程式的故障狀態,再次執行程式。但是錯誤出現了,程式會被終止。
另一個則是異常的處理過程。每一個異常都有一個異常號,核心的異常處理函式,會根據出現的異常號來做相應的操作。
程序是一種抽象,在執行的程式看來,自己擁有CPU和記憶體的使用權。程序切換的時候,需要儲存當前程式的上下文,以便未來恢復程式的狀態。這裡介紹了幾個函式:
- 獲取程序資訊:
getpid()
和getppid()
- 建立子程序:
fork()
- 終止程序:
exit()
- 在此程序上直接執行另一個程序
execve
這裡也介紹了程序圖,但是需要配合fork()
函式的行為來理解。
兩個部分介紹完了,下一個異常就是訊號了。訊號是後臺程式執行完畢後,核心給當前程序的一種通知。訊號可以被程序忽略。程序收到訊號後,有三種操作:
- 忽略
- 終止
- 交給訊號處理函式處理訊號
另一個異常就是非本地跳轉。本地跳轉就是程式在一個函式內的goto語句。非本地跳轉實現了兩個函式之間的跳轉。這裡講了兩個函式以及行為。
setjmp()
:執行後,會儲存當前函式的狀態longjmp()
:執行後,會恢復由setjmp
儲存的狀態,實現棧的切換。
還講了偽並行-併發和真正的並行區別,就是同時執行的程序,如果只有一個CPU來處理,那就是併發;如果多個核心分別執行多個程序,則為並行。