2018-2019-1 20165329 《資訊安全系統設計基礎》第七週學習總結
阿新 • • 發佈:2018-11-11
2018-2019-1 20165329 《資訊安全系統設計基礎》第七週學習總結
教材內容總結:
8.1異常
-
異常處理程式執行在核心模式下,它們對所以的系統資源都有完全的訪問許可權。
- 異常是異常控制流的一種形式,它一部分由硬體實現,一部分由作業系統實現。異常是控制流中的突變,用來響應處理器狀態中的某些變化。
-
異常的種類:異常可分為四類,中斷、陷阱、故障和終止。
-
陷阱是有意的異常,是執行一條指令的結果。
- 中斷是非同步產生的,是來自處理器外部的I/O裝置的訊號的結果。
-
故障由錯誤情況引起,它可能能夠被故障處理程式修正。
-
終止是不可恢復的致命錯誤造成的結果,通常是一些硬體錯誤。
- Linux/IA32故障和終止除法錯誤;一般保護故障;缺頁;機器檢查
- Linux/IA32系統呼叫:每個系統呼叫都有一個唯一的整數號,對應於一個到核心中跳轉表的偏移量。
- 暫存器%rax包含系統呼叫號
- 從系統呼叫返回時,暫存器%rcx和%rll都會被破壞,%rax包含返回值
如下圖所示:
8.2 程序
- 程序就是一個執行中的程式例項。系統中的每個程式都是執行在某個程序的上下文中的。
- 程序提供給應用程式的關鍵抽象:一個獨立的邏輯控制流 ;一個私有的地址空間。
- 程式計數器(PC)值的序列叫做邏輯控制流,簡稱邏輯流。
- 併發流:併發流一個邏輯流的執行在時間上與另一個流重疊,叫做並行流
- 併發:多個流併發執行的一般現象稱為併發。
- 多工:多個程序併發叫做多工。
- 並行:併發流在不同的cpu或計算機上,叫做並行。
- 地址空間底部是保留給使用者程式的,包括通常的程式碼、資料、堆和棧段。
- 程式碼段總是從地址0x400000開始。
- 排程:核心中的排程器實現排程。
- 上下文切換:儲存當前程序的上下文;恢復某個先前被搶佔的程序被儲存的上下文;將控制傳遞給這個新恢復的程序
- 當核心代表使用者執行上下文切換時,可能會發生上下文切換。如果系統呼叫發生阻塞,那麼核心可以讓當前程序休眠,切換到另一個程序。
8.4 程序控制
- getpid函式返回呼叫程序的PID。
- getppid函式返回它的父程序的PID
- 程序的三種狀態——執行、停止和終止。
- 程序會因為三種原因終止程序:(1)收到訊號,該訊號預設終止程序;(2)從主程式返回;(3)呼叫exit函式。
- fork函式:(1)呼叫一次,返回兩次;(2)併發執行;(3)相同但是獨立的地址空間;(4)共享檔案
- 回收:當一個程序終止時,核心並不立即把它從系統中清除。相反,程序被保持在一種已終止的狀態中,直到被它的父程序回收。
- 僵死程序:一個終止了但是還未被回收的程序稱為僵死程序。
- 回收子程序的兩種方法:核心的init程序;父程序waitpid函式
- waitpid函式有點複雜,預設地(當options=0時),waitpid掛起呼叫程序的執行,知道它的等待集合中的一個子程序終止。
- sleep函式將一個程序掛起一段指定的時間。
- 如果請求的時間量已經到了,sleep返回0,否則返回還剩下的要休眠的秒數。後一種情況是可能的,如果因為sleep函式被一個訊號中斷而過早地返回。
- pause函式讓呼叫函式休眠,直到該程序收到一個訊號。
- execve函式載入並執行可執行目標檔案filename,且帶引數列表argv和環境變數列表envp。與fork一次呼叫返回兩次不同,execve呼叫一次並從不返回。
- 引數中每個指標都指向一個引數串。
8.5 訊號
- 一種更高層次的軟體形式的異常,稱為unix訊號,它允許程序中斷其他程序。
- 低層的硬體異常是由核心異常處理程式處理的,正常情況下,對使用者程序而言是不可見的。訊號提供了一種機制,通知使用者程序發生了這些異常。
- 傳送一個訊號到目的程序是由兩個步驟組成的傳送訊號。核心通過更新目的程序上下文中的某個狀態,傳送(遞送)一個訊號給目的程序。傳送訊號可以有如下兩種原因:
- (1)核心檢測到一個系統事件。
- (2)一個程序呼叫了kill函式,顯式地要求核心傳送一個訊號給目的程序,一個程序可以傳送訊號給它自己。
- 接收訊號:當目的程序被核心強迫以某種方式的傳送做出反應時,目的程序就接收了訊號。程序可以忽略這個訊號,終止或者通過執行一個稱為訊號處理程式的使用者層函式不活這個訊號。
- 一個只發出而沒有被接收的訊號叫做待處理訊號。在任何時刻,一種型別至多隻會有一個待處理訊號。
- 一個程序可以有選擇性地阻塞接收某種訊號。當一種訊號被阻塞時,他仍可以被髮送,但是產生的待處理訊號不會被接收,直到程序取消對這種訊號的阻塞。一個待處理訊號最多隻能被接收一次。
- 程序組:每個程序都只屬於一個程序組,程序組是由一個正整數程序組ID來標識的。 一個子程序和它的父程序同屬於一個程序組,一個程序組可以通過使用setpgid函式來改變自己或者其他程序的程序組。
- 用/bin/kill程式傳送訊號,用/bin/kill程式可以向另外的程序傳送任意的訊號。
- 從鍵盤傳送訊號,從鍵盤傳送訊號外殼為每個作業建立一個獨立的程序組。
- 用kill函式傳送訊號程序通過呼叫kill函式傳送訊號給其他程序(包括它們自己)。
- 用alarm函式傳送訊號程序可以通過呼叫alarm函式向他自己傳送SIGALRM訊號。
- 當核心從一個異常處理程式返回,準備將控制傳遞給程序P時,他會檢查程序P的未被阻塞的處理訊號的集合。如果這個集合為空,那麼核心將控制傳遞到P的邏輯控制流中的下一條指令;如果集合是非空的,那麼核心選擇集合中的某個訊號K(通常是最小的K0,並且強制P接收訊號K。收到這個訊號會觸發程序的某種行為。一旦程序完成了這個行為,那麼控制就傳遞迴P的邏輯控制流中的下一條指令。
- 每個訊號型別都有一個預定的預設行為:
- (1)程序終止
- (2)程序終止並轉儲儲存器
- (3)程序停止直到被SIGCONT型號重啟
- (4)程序忽略該訊號
- signal函式可以通過下列三種方法之一來改變和訊號signum相關聯的行為:
- (1)如果handler是SIG_IGN,那麼忽略型別為signum的訊號
- (2)如果handler是SIG_DFL,那麼型別為signum的訊號行為恢復為預設行為
- (3)否則,handler就是使用者定義的函式的地址,這個函式成為訊號處理程式,只要程序接收到一個型別為signum的訊號,就會呼叫這個程式,通過把處理程式的地址傳遞到signal函式從而改變預設行為,這叫做設定訊號處理程式。
- 當一個程式要捕獲多個訊號時,一些細微的問題就產生了。
- (1)待處理訊號被阻塞。Unix訊號處理程式通常會阻塞當前處理程式正在處理的型別的待處理訊號。
- (2)待處理訊號不會排隊等待。任意型別至多隻有一個待處理訊號。因此,如果有兩個型別為K的訊號傳送到一個目的程序,而由於目的程序當前正在執行訊號K的處理程式,所以訊號K時阻塞的,那麼第二和訊號就簡單地被簡單的丟棄,他不會排隊等待。
- (3)系統呼叫可以被中斷。像read、wait和accept這樣的系統呼叫潛在地會阻塞程序一段較長的時間,稱為慢速系統呼叫。在某些系統中,當處理程式捕獲到一個訊號時,被中斷的慢速系統呼叫在訊號處理程式返回時不再繼續,而是立即返回給使用者一個錯誤的條件,並將errno設定為EINTR。
- Signal包裝函式設定的訊號處理程式的訊號處理語義:
- (1)只有這個處理程式當前正在處理的那種型別的訊號被阻塞
- (2)和所有訊號實現一樣,訊號不會排隊等候
- (3)只要有可能,被中斷的系統呼叫會自動重啟。
- (4)一旦設定了訊號處理程式,它就會一直保持,知道signal帶著handler引數為SIG_IGN或者SIG_DFL被呼叫。
8.6 非本地跳轉
- c語言提供了一種使用者級異常控制流形式,稱為本地跳轉。通過setjmp和longjmp函式來提供。
- setjmp函式只被呼叫一次,但返回多次:一次是當第一次呼叫setjmp,而呼叫環境儲存在緩衝區env中時,一次是為每個相應的longjmp呼叫。另一方面,longjmp只調用一次,但從不返回。sig—函式是setjmp和longjmp函式的可以被訊號處理程式使用的版本。
- 非本地跳轉的一個重要應用就是允許從一個深層巢狀的函式呼叫中立即返回,通常是由檢測到某個錯誤情況引起的。
- 非本地跳轉的另一個重要應用是使一個訊號處理程式分支到一個特殊的程式碼位置,而不是返回到達中斷了的指令位置。