1. 程式人生 > >第八章 異常控制流(下)

第八章 異常控制流(下)

程序控制:

每個程序都有一個唯一的整數程序PID。

程序一般可認為處於以下三種狀態:執行、停止、終止;

 

父程序可以通過呼叫fork函式建立一個新的執行的子程序。父程序和新建立的子程序之間最大的區別在於它們有不同的pid。

fork函式具有以下幾個特點:

1、呼叫一次,返回兩次。一次返回給父程序,一次返回到新建立的子程序。

2、併發執行。父程序和子程序是併發執行的獨立程序。

3、相同但是獨立的地址空間。父程序和子程序都有自己獨立的地址空間。

4、共享檔案。子程序繼承了父程序所有的開啟檔案。

 

回收子程序:

當一個程序由於某個原因終止時,核心並不是立即將它從系統中清除。相反,程序被保持在一種已終止的狀態中,直到被它的父程序回收。當父程序回收已終止的子程序時,核心將子程序的退出狀態傳遞給父程序,然後拋棄已終止的程序。從此時開始,該程序就不存在了。一個終止了但還未被回收的程序被稱為僵死程序。

 

如果一個父程序終止了,核心會安排init程序去回收它們。init程序的pid為1,是在系統啟動時由核心建立的,它不會終止,是所有程序的祖先。

 

 

訊號:

訊號:通知程序系統中發生了一個某種型別的事件。

每個訊號型別都對應於某種系統事件。訊號提供了一種機制,通知使用者程序發生了這些異常。比如,如果一個程序試圖除以0,那麼核心會發送給它一個SIGFPE的訊號。

 

傳送一個訊號到目的程序分兩個步驟:

1、傳送訊號。核心通過更新目的程序上下文中的某個狀態,傳送一個訊號給目的程序。傳送訊號可以由如下兩種原因:

     1)核心檢測到一個系統事件,比如除零錯誤或終止程序。

     2)一個程序呼叫了kill函式

傳送訊號有幾種形式:

     1)用/bin/kill程式傳送訊號

     2)從鍵盤傳送訊號

     3)用kill函式傳送訊號

     4)用alarm函式傳送訊號

2、接收訊號:當目的程序被核心強迫以某種方式對訊號的傳送做出反應時,它就接收了訊號。程序可以忽略這個訊號,終止或者通過執行一個訊號處理程式的使用者層函式捕獲這個訊號。

      一個發出而沒有被接收的訊號被稱為待處理訊號。如果一個程序有一個型別k的待處理訊號,那麼任何接下來發送到這個程序的型別為k的訊號都不會排隊等待,它們只是被簡單的丟棄。

 

舉一個例子:

傳送三個SIGCHLD訊號給父程序,但是其中只有兩個訊號被接收了。why?

解釋如下:當第一個訊號到達時,父程序接收並捕獲到第一個訊號。當處理程式還在處理第一個訊號時,第二個訊號就傳送並新增到了待處理訊號集合裡。然而,因為SIGCHLD訊號被SIGCHLD處理程式阻塞了,所以第二個訊號就不會被接收。此後不久,就在處理程式還在處理第一個訊號時,第三個訊號到達了。因為已經有了一個待處理的SIGCHLD訊號,第三個SIGCHLD訊號就會被丟棄。這也就是為何最後父程序這邊只有兩個訊號被接收了。

 

因此,需牢記:不可以用訊號來對其他程序中發生的事件計數。

 

非本地跳轉:

非本地跳轉有兩個重要應用:

1、允許從一個深層巢狀的函式呼叫中立即返回,通常是由檢測到某個錯誤情況引起的。如果在一個深層巢狀的函式呼叫中發現了一個錯誤情況,我們可以使用非本地跳轉直接返回到一個普通的本地化的錯誤處理程式,而不是費力的解開呼叫棧。

2、使一個訊號處理程式分支到一個特殊的程式碼位置,而不是返回到被訊號到達中斷了的指令的位置。