返回主目錄算法
以前的有博文對進程和線程的區別進行了詳細的介紹,而且說明了引入進程的目的是爲了可以使程序併發的執行,而且能夠對併發執行的程序加以描述和控制。這篇博文,咱們就來對進程的狀態轉換來進行詳細的分析。本文除了進程的狀態轉換,還穿插着對進程的控制的說明。緩存
注意:本博文中進程均是在傳統操做系統中的進程,既是OS進行資源分配的基本單位,也是OS進行調度的一個獨立單位。markdown
在開始以前,咱們對進程和程序來進行一個對比:數據結構
- 程序是靜態的,而進程是動態的。
- 程序能夠做爲一種軟件資源長期存在,而進程是有必定生命週期的。程序是永久的,進程是暫時的。
- 進程更能真實地描述併發,而程序不能;
- 進程具備建立其餘進程的功能,而程序沒有;
- 同一程序能夠對應多個進程;
- 進程是系統分配資源和調度的獨立單位,而程序不是。
所以,從上面咱們能夠獲得進程的一些特徵:併發
- 動態性(進程由建立而產生,由調度而執行,由撤銷而消亡);
- 併發性(多個進程同存於內存中,能夠併發的執行);
- 獨立性(資源分派和調度的獨立單位);
- 異步性(進程的執行以一種不可預知的速度向前推動)。
三種基本狀態
上面咱們講到了,進程是具備生命週期的,由建立而產生,由調度而執行,由撤銷而消亡,而且內存中能夠同時存在多個進程,多個進程在併發執行的過程當中共享系統資源,由於資源的爭用或者其餘緣由,致使進程在運行的過程當中呈現間斷性(異步),所以,進程在其生命週期內就具備多種狀態。異步
首先咱們講的是三種基本狀態:就緒態、執行態、阻塞態。這三種基本狀態是每一個OS中都會有的,所以也稱之爲基本狀態,下面先給出三種基本狀態的定義:性能
- 就緒(Ready)狀態:經過Ready咱們能夠看到,處於此狀態的進程已經處於準備好要運行了,此時進程已經分配好除CPU外的全部必要資源,只需得到CPU(CPU如何進行分配,請關注後續有關處理機調度的博文),即可當即執行。用一句話來描述處於就緒態的進程:萬事俱備,只欠CPU。另外還有一個就緒隊列的概念,處於就緒態的進程都在此隊列中,等待着調度程序的調度(分配CPU)。
- 執行(Running)狀態:Running,運行中的,處於此狀態的進程是已經得到CPU而且正在執行中。對於這一狀態,在單CPU OS中,同一時刻只能有一個進程處於此狀態,而在多CPU OS中,則能夠有多個(不超過CPU的數量)進程同時處於執行狀態。
- 阻塞(Block)狀態:阻塞,百度釋義爲:障礙而不能經過,沒法暢通。處於此狀態的進程是由於在執行的過程當中因爲發生某種須要等待的事件(I/O請求、申請緩存失敗、等待接收數據等),而暫時沒法繼續執行。咱們知道在多道批處理系統中,此時須要進程把處理機釋放,並選取新的就緒進程執行。與就緒隊列相對應的,處於阻塞狀態的進程都在阻塞隊列中,某些OS中,出於提升效率的目的,根據阻塞的緣由,會有多個阻塞隊列。
上圖是進程的三種基本狀態的轉換圖,進程在運行的過程當中會常常的發生狀態的轉換。從圖中咱們能夠看到,就緒態和執行態是能夠互相轉換的,可是執行態到阻塞態是單向的,這是由於就算阻塞的進程"通暢"了,可是由於處理機已經分配給了別的進程,所以進程的狀態也只能切換到就緒態,而且也是單項的,由於等待事件也只能夠在執行中才能發生,下面說明下各個狀態切換髮生的緣由:學習
- 就緒態—>執行態:進程得到CPU(被調度程序選中);
- 執行態—>阻塞態:向OS請求共享資源(互斥、同步)失敗、等待某種操做完成、新數據還沒有到達(I/O操做)、等待新任務的到達;
- 阻塞態—>阻塞態:上述的四類等待事件發生;
- 執行態—>就緒態:分配給進程的時間片執行完成(輪轉調度算法)、高優先級的進程到達(搶佔式調度)。
建立狀態和終止狀態
咱們知道,進程建立時,須要對其分配除CPU外的全部的必要資源,可是,若是此時OS由於資源不足沒法給進程分配資源,那麼進程應該處於什麼狀態呢?爲了知足上述問題,知足進程狀態的完整性以及加強管理的靈活性,一般會在OS中爲進程新增兩種常見的狀態:建立狀態和終止狀態。下面給出兩種狀態的定義:atom
- 建立狀態:進程建立的過程當中,所需的資源尚不能獲得知足,此時建立工做還沒有完成,進程沒法被調度執行,進程此時就處於建立狀態。
- 終止狀態:進程正常運行結束或者出現致使進程終止的錯誤,或是被OS所終結,或是被父進程終結,則進入終止狀態。進入終止狀態的進程將不能再執行,可是在OS中依然保持一個記錄,其中保存着狀態碼和計時統計數據,等待別的進程收集,一旦資源被收集完成,OS會馬上刪除該進程。
包含建立狀態和終止狀態以後,進程的狀態轉換如上圖所示。從圖中咱們能夠看到,狀態的轉換多了建立態到就緒態,執行態到終止態,下面給出兩種狀態切換的緣由:spa
- 建立態—>就緒態:進程所需的資源獲得分配;
- 執行態—>終止態:進程正常運行結束或者出現致使進程終止的錯誤,或是被OS所終結,或是被父進程(或其餘有終止權的進程)終結。
下面對進程建立和終止的過程來進行一下說明。首先是進程的建立,進程的建立是一個較爲複雜的過程,首先須要由進程申請一個空白的進程控制塊(Process Control Block, PCB,後面會詳細的講),並向PCB中填寫用於控制和管理進程的信息;而後爲該進程分配運行時必要的資源;最後把該進程轉爲就緒態並插入到就緒隊列中。其次是進程的終止,進程的終止分爲兩個步驟:首先是等待OS進行善後處理(中止執行、終止子孫進程、歸還資源等),而後將其PCB清零,並將PCB空間返還給系統。
從上述進程的建立和終止的過程當中,咱們能夠得知,建立態就是處於進程建立的第一步完成時的狀態,終止態就是進程沒法被調度或執行,可是還需等待別的進程來收集信息,也就是終止態一樣處於第一步完成的狀態,只有當進程歸還了PCB後,纔算是真正的被OS刪除,生命週期纔算結束。
掛起、激活操做
在部分OS中,爲了系統和用戶觀察和分析進程的須要,還引入了一個對進程的重要操做—掛起(Suspend),當對某個進程執行此操做是時,該進程將會被掛起,此時意味着該進程須要釋放內存,調至到硬盤中(外存),也意味着此時該進程處於靜止狀態,沒法接受調度或者執行。當該進程被執行激活(Active)操做時,纔可將該進程從外存中從新導入到內存中。
首先咱們來分析下進程被掛起的緣由:
- 終端用戶的請求:當終端用戶在本身的程序運行期間發現有可疑問題時,但願暫停本身的程序的運行,使之中止下來,以便用戶研究其執行狀況或對程序進行修改;
- 父進程的請求:有時父進程但願掛起本身的某個子進程,以便考察和修改子進程,或者協調各子進程間的活動;
- 負荷調節的須要:當實時系統中的工做負荷較重,已可能影響到對實時任務的控制時,可由系統把一些不重要的進程掛起,以保證系統能正常運行;
- 操做系統的須要:操做系統有時但願掛起某些進程,以便檢查運行中的資源使用狀況或進行記帳。
引入掛起以後,系統中的就緒狀態和阻塞狀態分別變爲兩種狀態,這四種狀態爲:活動就緒、靜止就緒、活動阻塞、靜止阻塞,下面分別對這四種狀態進行說明:
- 活動就緒(Readya):等價於就緒態,此時進程能夠接受調度,得到處理機後可直接轉爲執行態;
- 靜止就緒(Readys):進程被調至外存,沒法接受調度;
- 活動阻塞(Blockeda):等價於阻塞態,當等待的事件發生後能夠由活動阻塞變爲活動就緒狀態;
- 靜止阻塞(Blockeds):進程仍然能夠等待事件,當事件發生後,狀態由靜止阻塞變爲靜止就緒狀態。
引入掛起操做後,OS中的狀態變爲7種,其中部分進程狀態的變化以下:
- 活動就緒—>靜止就緒:該進程被執行掛起原語Suspend;
- 活動阻塞—>靜止阻塞:該進程被執行掛起原語Suspend;
- 執行態—>靜止就緒:該進程被執行掛起原語Suspend;
- 靜止就緒—>活動就緒:該進程被執行掛起原語Active;
- 靜止阻塞—>活動阻塞:該進程被執行激活原語Active;
- 靜止阻塞—>靜止就緒:進程等待的事件發生;
- 活動阻塞—>活動就緒:進程等待的事件發生;
- 建立態—>活動就緒:在當前OS的性能和內存的容量均容許的狀況下,完成進程的建立工做(三步);
- 建立態—>靜止就緒:當前OS的當前資源情況和性能不容許,不分配給新建進程所需的資源(建立工做只完成第一步),此時進程處於靜止就緒狀態,被調至到外存中,不參與調度,此時建立工做還沒有完成。
從上面的狀態咱們能夠看到,處於執行態的進程同樣會被掛起,並且引入了掛起操做後,進程不會長期的處於建立狀態,若是能分配到資源,狀態會變爲活動就緒態,若是沒法分配資源,則進入靜止就緒狀態,當資源充足後,在將進程調入內存併爲之分配資源,完成建立工做。
進程控制塊PCB
上面講了這麼多的進程的狀態的切換,那麼OS究竟是根據什麼來進行進程的控制和管理呢?好比進程的狀態信息保存在哪裏、進程對應的程序和數據是如何保存的、進程是如何保存和恢復CPU現場信息(上下文切換)的,還有其餘等等操做是如何實現的?其實這些操做都須要依託於一種數據結構—進程控制塊PCB。PCB是OS爲了系統的描述和管理進程的運行,在內核中爲每一個進程專門定義的一個數據結構。PCB做爲進程實體(程序、數據、PCB)的一部分,記錄了OS所需的用於描述進程當前狀況以及管理進程運行的所有信息,是OS中最重要的記錄型數據結構。
**PCB的做用是使一個在多道程序環境下不能獨立運行的程序(含數據),成爲一個能獨立運行的基本單位,一個能與其它進程併發執行的進程。**所以PCB的做用很是重要,咱們講進程的狀態切換是必需要講PCB的。首先,咱們對PCB中存儲的信息進行介紹:
- 進程標識符:用於惟一地標識進程。一個進程一般包含兩種標識符:外部標識符和內部標識符。外部標識符通常由建立者(用戶)提供,用來方便記憶;內部標識是爲了方便OS對進程的使用,一般是Linux系統中查看到的Pid;
- CPU狀態:CPU狀態信息也稱處理機的上下文,主要由CPU的各類寄存器(通用寄存器、指令計數器、程序狀態字PSW、用戶棧指針)中的內容組成的。進程在執行的過程當中,正在處理的許多信息都放在寄存器中,若是須要發生切換,這些信息就須要保存在該進程的PCB中,以即可以再次執行時能夠快速的恢復CPU的狀態;
- 進程調度信息:在OS進行調度(從就緒隊列中選取進程分配CPU)時,必需要知道進程的狀態和相關的調度信息,主要包括:進程狀態、優先級、進程調度所需的其餘信息(等待時間、已經執行的時間等)、事件(等待發生的時間,即阻塞的緣由);
- 進程的控制信息:只用於進程控制所必需的信息,主要包括:程序和數據的地址(所在內存或外存的首地址)、進程同步和通訊機制、資源清單(進程運行期間所需的所有資源,CPU除外,還有一張已經分配給該進程的資源清單,主要用於避免死鎖)、連接指針(指向本PCB所在隊列中的下一個進程的PCB的首地址)。
經過PCB所保存的信息,咱們是否是也就知道了上面講到的問題(進程如何進行控制、程序和數據如何保存、CPU上下文如何切換和恢復)的答案了,都是須要使用PCB中保存的信息。下面咱們根據PCB中存儲的信息,來對PCB做用作一個具體的分析:
- 做爲獨立運行基本單位的標誌:當一個程序(包含數據)配置了PCB後,就表示他成爲了一個進程,一個能在多道程序環境下獨立運行併合法的一個基本單位,也就具備了取得OS服務的權利。這也是爲何當系統建立一個進程時,須要爲之建立一個PCB,並與進程一對一的綁定,系統是根據PCB來感知進程的,PCB被撤銷歸還給OS時,進程也就隨之消亡了;
- 能實現間斷運行的方式:這也是進程的一個基本特性—異步性,由於PCB中保存着進程在CPU上執行時的上下文信息,所以在進程再次被調度執行時,能夠快速的恢復其CPU的現場信息。
- 提供進程管理所須要的信息:在進程的整個生命週期中,OS都是根據PCB實施對進程的控制和管理。
- 提供進程調度所須要的信息:OS根據PCB中存儲的進程的狀態信息來將繼承插入到對應的隊列中,並根據PCB中保存的優先級、等待事件等來進行調度的;
- 實現與其餘進程的同步與通訊:PCB中具備用與實現進程通訊的區域或通訊隊列指針等。
經過上面的描述,咱們也看到了PCB的重要之處,雖然一個進程中的PCB保存瞭如此多的信息,可是一個PCB的大小大約是1KB左右,體量小也能夠保證內核中能夠存放必定數量的PCB。
又到了分隔符如下,本文到此就結束了,本文內容所有都是由博主本身進行整理並結合自身的理解進行總結,若是有什麼錯誤,還請批評指正,固然,若是有什麼疑惑能夠評論留言。
全文又是4700多字,原創不易,在寫這篇博客的時候,真的是投入了大量的心血,翻看了許多的文檔,若是本文對你有所幫助,還請留下個贊,以表支持。