linux系統程式設計之程式(二):程式生命週期與PCB(程式控制塊)

mickole發表於2013-07-12

本節目標:

  • 程式狀態變遷
  • 程式控制塊
  • 程式建立
  • 程式撤消
  • 終止程式的五種方法

一,程式狀態變遷

程式的三種基本狀態

就緒(Ready)狀態

當程式已分配到除CPU以外的所有必要的資源,只要獲得處理機便可立即執行,這時的程式狀態稱為就緒狀態。

執行(Running)狀態
當程式已獲得處理機,其程式正在處理機上執行,此時的程式狀態稱為執行狀態。

阻塞(Blocked)狀態
正在執行的程式,由於等待某個事件發生而無法執行時,便放棄處理機而處於阻塞狀態。引起程式阻塞的事件可有多種,例如,等待I/O完成、申請緩衝區不能滿足、等待信件(訊號)等。

狀態轉換圖:

211321570

一個程式在執行期間,不斷地從一種狀態轉換到另一種狀態,它可以多次處於就緒狀態和執行狀態,也可以多次處於阻塞狀態。

(1) 就緒→執行
處於就緒狀態的程式,當程式排程程式為之分配了處理機後,該程式便由就緒狀態轉變成執行狀態。

(2) 執行→就緒
處於執行狀態的程式在其執行過程中,因分配給它的一個時間片已用完或更高優先順序的程式搶佔而不得不讓出處理機,於是程式從執行狀態轉變成就緒狀態。

(3) 執行→阻塞
正在執行的程式因等待某種事件發生而無法繼續執行時,便從執行狀態變成阻塞狀態。

(4) 阻塞→就緒
處於阻塞狀態的程式,若其等待的事件已經發生,於是程式由阻塞狀態轉變為就緒狀態。

(5) 執行→終止

程式執行完畢,撤銷而終止

 

以上是最經典也是最基本的三種程式狀態,但現在的作業系統都根據需要重新設計了一些新的狀態。

如linux:

  • 執行狀態(TASK_RUNNING):是執行態和就緒態的合併,表示程式正在執行或準備執行,Linux 中使用TASK_RUNNING 巨集表示此狀態
  • 可中斷睡眠狀態(淺度睡眠)(TASK_INTERRUPTIBLE):程式正在睡眠(被阻塞),等待資源到來是喚醒,也可以通過其他程式訊號或時鐘中斷喚醒,進入執行佇列。Linux 使用TASK_INTERRUPTIBLE 巨集表示此狀態。
  • 不可中斷睡眠狀態(深度睡眠狀態)(TASK_UNINTERRUPTIBLE):
  • 其和淺度睡眠基本類似,但有一點就是不可被其他程式訊號或時鐘中斷喚醒。Linux 使用TASK_UNINTERRUPTIBLE 巨集表示此狀態。

  • 暫停狀態(TASK_STOPPED):程式暫停執行接受某種處理。如正在接受除錯的程式處於這種狀態,Linux 使用TASK_STOPPED 巨集表示此狀態。
  • 僵死狀態(TASK_ZOMBIE):程式已經結束但未釋放PCB,Linux 使用TASK_ZOMBIE 巨集表示此狀態

狀態轉換圖如下:

QQ截圖20130712103012


      就緒態在支援虛擬記憶體的作業系統中可能分為:在記憶體中就緒和在交換空間就緒,因為支援虛擬記憶體的作業系統會將當前不太活躍的一些程式交換到交換空間,交換空間就緒程式要執行要先換人記憶體出入記憶體就緒態,在由cpu排程執行。

二,程式控制塊(PCB)

程式控制塊包括:

程式描述資訊:

  • 程式識別符號用於唯一的標識一個程式(pid,ppid)。

程式控制資訊:

  • 程式當前狀態
  • 程式優先順序
  • 程式開始地址
  • 各種計時資訊
  • 通訊資訊

資源資訊:

  • 佔用記憶體大小及管理用資料結構指標
  • 交換區相關資訊
  • I/O裝置號、緩衝、裝置相關的數結構
  • 檔案系統相關指標

現場保護資訊(cpu進行程式切換時):

  • 暫存器
  • PC
  • 程式狀態字PSW
  • 棧指標

 

程式標識:PID

  • 每個程式都會分配到一個獨一無二的數字編號,我們稱之為“程式標識”(process identifier),或者就直接叫它PID.
  • 是一個正整數,取值範圍從2到32768

     可以通過:cat /proc/sys/kernel/pid_max 檢視系統支援多少程式

  • 當一個程式被啟動時,它會順序挑選下一個未使用的編號數字做為自己的PID
  • 數字1一般為特殊程式init保留的

         init程式實際上是使用者程式,它是一個程式,在/sbin/init,linux啟動的第一個程式

        實際上linux中還存在0號程式(核心程式),它是一個空閒程式,它進行空閒資源的統計及交換空間的換入換出,1(init)程式是由0號程式建立的。

 

三,程式建立

  • 不同的作業系統所提供的程式建立原語的名稱和格式不盡相同,但執行建立程式原語後,作業系統所做的工作卻大致相同,都包括以下幾點:
  • 給新建立的程式分配一個內部標識(pcb),在核心中建立程式結構。
  • 複製父程式的環境
  • 為程式分配資源, 包括程式映像所需要的所有元素(程式、資料、使用者棧等),
  • 複製父程式地址空間的內容到該程式地址空間中。
  • 置該程式的狀態為就緒,插入就緒佇列。

 

四,程式撤銷

程式終止時作業系統做以下工作:

  • 關閉軟中斷:因為程式即將終止而不再處理任何軟中斷訊號;
  • 回收資源:釋放程式分配的所有資源,如關閉所有已開啟檔案,釋放程式相應的資料結構等;
  • 寫記帳資訊:將程式在執行過程中所產生的記帳資料(其中包括程式執行時的各種統計資訊)記錄到一個全域性記帳檔案中;
  • 置該程式為僵死狀態:向父程式傳送子程式死的軟中斷訊號,將終止資訊status送到指定的儲存單元中;
  • 轉程式排程:因為此時CPU已經被釋放,需要由程式排程進行CPU再分配。

五,終止程式的五種方法

  • 從main函式返回:從return返回,執行完畢退出
  • 呼叫exit:C函式庫,實際上也是呼叫系統呼叫_exit完成的,在任何一個函式呼叫exit函式都可使得程式撤銷
  • 呼叫_exit:系統呼叫
  • 呼叫abort:呼叫abort()函式使得程式終止,實際上該函式是產生一個SIGABRT訊號,
  • 由訊號終止:傳送一些訊號如SINGINT等訊號

相關文章