20145320《信息安全系統設計基礎》第11周學習總結

第八章 異常控制流

  • 控制流:控制轉移序列。linux

  • 控制轉移:從一條指令到下一條指令。
  • 異常控制流:現代操做系統經過使控制流發生突變來對系統狀態作出反應,這些突變稱爲異常控制流。數組

8.1 異常

異常的剖析,以下圖所示:bash

異常處理

  • 異常表:當處理器檢測到有事件發生時,它會經過跳轉表,進行一個間接過程調用(異常),到異常處理程序。服務器

  • 異常號:系統中可能的某種類型的異常都分配了一個惟一的非負整數的異常號。異常號是到異常表中的索引。數據結構

  • 一旦硬件觸發了異常,異常處理程序則由軟件完成。併發

異常的類別

  • 異常的類別——中斷、陷阱、故障和終止

linux/ia32系統中的異常

  • Linux/IA32故障和終止函數

    - 除法錯誤
     -  通常保護故障
     - 缺頁
     - 機器檢查
  • Linux/IA32系統調用
    • 每一個系統調用都有一個惟一的整數號,對應於一個到內核中跳轉表的偏移量。

進程

  • 進程(操做系統層):邏輯控制流,私有地址空間,多任務,併發,並行,上下文,上下文切換,調度。
  • 進程就是一個執行中的程序實例。系統中的每一個程序都是運行在某個進程的上下文中的。
  • 進程提供給應用程序的關鍵抽象:a)一個獨立的邏輯控制流 ;b)一個私有的地址空間。

邏輯控制流

程序計數器(PC)值的序列叫作邏輯控制流,簡稱邏輯流。以下圖所示,處理器的一個物理控制流分紅了三個邏輯流,每一個進程一個。學習

用戶模式和內核模式

運行應用程序代碼的進程初始時是在用戶模式中的。進程從用戶模式變爲內核模式的惟一方法是經過異常。
linux提供了/proc文件系統,它容許用戶模式進程訪問內核數據結構的內容。

上下文切換

  • 上下文切換:操做系統內核使用叫上下文切換的異常控制流來實現多任務。
  • 上下文切換:a)保存當前進程的上下文;b)恢復某個先前被搶佔的進程被保存的上下文; c)將控制傳遞給這個新恢復的進程
    • 調度:內核中的調度器實現調度。
    • 當內核表明用戶執行上下文切換時,可能會發生上下文切換。若是系統調用發生阻塞,那麼內核可讓當前進程休眠,切換到另外一個進程,如read系統調用,或者sleep會顯示地請求讓調用進程休眠。通常,即便系統調用沒有阻塞,內核亦能夠決定上下文切換,而不是將控制返回給調用進程。ui

    • 中斷也可能引發上下文切換。如,定時器中斷。操作系統

進程控制

獲取進程id

建立和終止進程

  • 進程的三種狀態——運行、中止和終止。
  • 進程會由於三種緣由終止進程:收到信號,該信號默認終止進程;從主程序返回;調用exit函數。


回收子進程

  • 回收:當一個進程終止時,內核並不當即把它從系統中清除。相反,進程被保持在一種已終止的狀態中,直到被它的父進程回收。
  • 僵死進程:一個終止了可是還未被回收的進程稱爲僵死進程。
  • 回收子進程的兩種方法:1,內核的init進程 2,父進程waitpid函數
    • 1)若是父進程沒有回收它的僵死子進程就終止了,那麼內核就會安排init進城來回收它們。init進程的PID爲1,而且是在系統初始化時建立的。
    • 2)一個進程能夠經過調用waitpid函數來等待它的子進程終止或中止。
  • waitpid函數有點複雜,默認地(當options=0時),waitpid掛起調用進程的執行,知道它的等待集合中的一個子進程終止。

    1.斷定等待集合的成員
      2.修改默認行爲
      3.檢查已回收子進程的退出狀態
      4.錯誤條件
      5.wait函數
      6.使用waitpid的示例

讓進程休眠

  • sleep函數將一個進程掛起一段指定的時間。

  • 若是請求的時間量已經到了,sleep返回0,不然返回還剩下的要休眠的秒數。後一種狀況是可能的,若是由於sleep函數被一個信號中斷而過早地返回。咱們將在8.5節中詳細討論信號

  • pause函數讓調用函數休眠,直到該進程收到一個信號。

加載並運行程序

  • execve函數加載並運行可執行目標文件filename,且帶參數列表argv和環境變量列表envp。只有當出現錯誤時,例如找不到filename,execve纔會返回到調用程序。因此,與fork一次調用返回兩次不一樣,execve調用一次並從不返回。

  • 參數中每一個指針都指向一個參數串。按照慣例,argv[0]是可執行目標文件的名字。環境變量的列表是由一個相似的數據結構表示的。envp變量指向一個以null結尾的指針數組,其中每一個指針指向個環境變量串,其中每一個串都是形如「NAME=VALUE」的名字一值對。

利用fork和execve運行程序

  • 像Unix外殼和Web服務器這樣的程序大量使用了fork和e×ecve函數。外殼是一個交互型的應用程序,它表明用戶運行其餘程序。最先的外殼是Sh程序,後面出現了一些變種,好比csh、tcsh、ksh和bash。外殼執行一系列的讀/求值(readeaUte)步驟而後終止。

  • 若是builtin_command返回0,那麼外殼建立一個子進程,並在子進程中執行所請求的程序。若是用戶要求在後臺運行該程序,那麼外殼返回到循環的頂部,等待下一個命令行不然,外殼使用Waitpid函數等待做業終止。看成業終止時,外殼就開始下一輪迭代。注意這個簡單的外殼是有缺陷的,由於它並不回收它的後臺子進程。修改這個缺陷就要求使用信號。

信號

  • 一種更高層次的軟件形式的異常,稱爲unix信號,它容許進程中斷其餘進程。
  • 低層的硬件異常是由內核異常處理程序處理的,正常狀況下,對用戶進程而言是不可見的。信號提供了一種機制,通知用戶進程發生了這些異常。

發送信號

  • 1.進程組

    • 進程組。每一個進程都只屬於一個進程組,進程組是由一個正整數進程組ID來標識的。 一個子進程和它的父進程同屬於一個進程組,一個進程組能夠經過使用setpgid函數來改變本身或者其餘進程的進程組。
  • 2.用/bin/kill程序發送信號
    • 用/bin/kill程序能夠向另外的進程發送任意的信號。
  • 3.從鍵盤發送信號
    • 從鍵盤發送信號外殼爲每一個做業建立一個獨立的進程組。
  • 4.用kill函數發送信號
    • 進程經過調用kill函數發送信號給其餘進程(包括它們本身)。
  • 5.用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函數從而改變默認行爲,這叫作設置信號處理程序。
  • 但一個進程不活了一個類型爲K的信號時,爲信號K設置的處理程序被調用,一個整數參數被設置爲K。這個參數容許同一個處理函數捕獲不一樣類型的信號。
  • 信號處理程序的執行中斷main C函數的執行,相似於底層異常處理程序中斷當前應用程序的控制流的方式,由於信號處理程序的邏輯控制流與主函數的邏輯控制流重疊,信號處理程序和主函數併發地運行。

信號處理問題

  • 當一個程序要捕獲多個信號時,一些細微的問題就產生了。
    • (1)待處理信號被阻塞。Unix信號處理程序一般會阻塞當前處理程序正在處理的類型的待處理信號。
    • (2)待處理信號不會排隊等待。任意類型至多隻有一個待處理信號。所以,若是有兩個類型爲K的信號傳送到一個目的進程,而因爲目的進程當前正在執行信號K的處理程序,因此信號K時阻塞的,那麼第二和信號就簡單地被簡單的丟棄,他不會排隊等待。
    • (3)系統調用能夠被中斷。像read、wait和accept這樣的系統調用潛在地會阻塞進程一段較長的時間,稱爲慢速系統調用。在某些系統中,當處理程序捕獲到一個信號時,被中斷的慢速系統調用在信號處理程序返回時再也不繼續,而是當即返回給用戶一個錯誤的條件,並將errno設置爲EINTR。
  • 不能夠用信號來對其餘進程中發生的事件計較。

可移植的信號處理

  • Signal包裝函數設置的信號處理程序的信號處理語義:
    • (1)只有這個處理程序當前正在處理的那種類型的信號被阻塞
    • (2)和全部信號實現同樣,信號不會排隊等候
    • (3)只要有可能,被中斷的系統調用會自動重啓。
    • (4)一旦設置了信號處理程序,它就會一直保持,知道signal帶着handler參數爲SIG_IGN或者SIG_DFL被調用。

      顯式地阻塞和取消阻塞信號517

代碼學習

fork函數

1.forkdemo1

  • 使用fork建立子進程的父進程,調用fork一次,打印兩個輸出行

二、forkdemo2

-調用兩次fork,一共產生四個子進程,打印四個輸出行,規律爲2的n次方

三、forkdemo3

  • 父進程返回才調用進程子進程。

四、forkdemo4

  • getpid返回調用進程的PID

  • getppid返回它的父進程的PID

五、forkgdb

  • 父進程和子進程這兩個線程是併發運行的獨立進程,一個在休眠時另外一個在執行,兩個相互獨立不干擾。

exec函數

一、exec1

  • 這裏展現的是ls -l,能夠修改代碼讓他執行其餘的命令。

二、exec2

  • exev1與exev2運行結果相同,區別在於exevp的第一個參數,exec1傳的是ls,exec2直接用的arglist[0]——>ls,可得這兩個等價,因此運行結果是相同的。

三、exec3

-此程序指定了環境變量,而後依然執行了ls -l指令,成功後沒有返回,因此最後一句話不會輸出,結果依然相同。

wait函數

一、waitdemo1

二、waitdemo2

  • 獲取子進程狀態,把狀態拆分紅三塊,exit,sig和core。

psh

一、psh1

  • 輸入要執行的指令,回車表示輸入結束,而後輸入的每一個參數對應到函數中,再調用對應的指令。

二、psh2

  • 比剛剛多了一個循環

代碼託管

  • 反正上傳的都是老師給的代碼...
相關文章
相關標籤/搜索