1. 程式人生 > 實用技巧 >OS-處理機排程與死鎖

OS-處理機排程與死鎖

第三章 處理機排程與死鎖

學習自《計算機作業系統》第五版

處理機=處理器(cpu)+主儲存器+輸入輸出裝置介面

記憶體中的程序數目往往多於處理機數目,所以需要系統按某種演算法,動態地分配處理機給就緒狀態的一個程序,分配處理機的任務由處理機排程程式完成。

目錄

處理機排程

排程層次

  • 高階排程,又稱作業排程,排程物件是作業,主要功能是決定將外存上處於後備佇列的哪些作業調入記憶體、為它們建立程序分配資源,並將它們放入就緒佇列。(高階排程主要存在於多道批處理系統。)
  • 中級排程,又稱記憶體排程,主要目的是提高記憶體利用率和系統吞吐量。該排程會把那些暫時無法執行的程序調到外存等待,此時被調程序的狀態稱為就緒駐外存(掛起)狀態;當它們符合繼續執行的條件而且記憶體也有足夠的空間時會被重新調入記憶體,此時再調入記憶體並修改為就緒狀態,掛在就緒佇列等待,中級排程實質上就是儲存器管理中的對換Swap
    功能。
  • 低階排程,又稱程序排程,排程物件是程序或者核心級執行緒,該排程決定就緒佇列中的哪個程序應獲得處理機,並由分派程式把處理機分配給被選中的程序。程序排程是最基本的排程,即多道批處理、分時、實時系統,都應該配置這類排程。

排程演算法的目標

飢餓現象,簡單來說就是作業等待時間過長,類似人等待吃飯過久而飢餓

  • 處理機排程演算法的共同目標

    • 資源利用率
      • 要提高資源利用率,就要儘可能使CPU處於忙碌狀態
      • CPU的利用率 = CPU有效工作時間/(CPU有效工作時間+CPU空閒等待時間)
    • 公平性
      • 所有程序都獲得合理的CPU時間,不會發生程序飢餓現象(相對的公平)
    • 平衡性
    • 策略強制執行
  • 批處理系統的目標

    • 平均週轉時間短

      • 週轉時間即從作業提交到作業完成經過的時間,

      • 即 週轉時間=結束時間-進入時間,包括四部分:

        • 作業在外存後備佇列上等待作業排程的時間
        • 程序在就緒佇列上等待程序排程的時間
        • 程序在CPU上執行的時間
        • 程序等待I/0操作完成的時間
      • 平均週轉時間可以表示為:
        $$
        T=\frac{1}{n}\sum_{i=1}^nT_i=\frac{總週轉時間}{作業數}
        $$

  • 為了更好地描述排程的效能,往往採用帶權週轉時間,即週轉時間Ti和執行時間Ts的比值,平均帶權週轉時間可以表示為:
    $$
    W=\frac{1}{n}\sum_{i=1}^n\frac{T_i}{T_s}
    $$

    • 系統吞吐量高

      • 吞吐量即單位時間系統完成的作業數,顯然長度短的作業更容易完成,可以讓吞吐量更高
    • 處理機利用率高

      • 處理機利用率高則要求作業儘可能長,與系統吞吐量高的做法矛盾
  • 分時系統的目標

    • 響應時間快
      • 即從使用者輸入提交一個請求直到得到處理結果為止的時間儘可能短。
      • 響應時間包含三部分:
        • 從輸入請求資訊直到其被傳送至處理機的時間
        • 處理機對請求的處理時間
        • 把處理結果回傳給使用者的時間
    • 均衡性
      • 系統響應的快慢應與使用者請求服務的複雜性相適應
  • 實時系統的目標

    • 截止時間的保證
      • 截止時間指某任務必須開始執行的最遲時間或必須完成的最遲時間
    • 可預測性
      • 在實時系統中很多請求都是可預測的,如視訊的播放,如果系統採用雙緩衝,則因為可實現第i幀播放和第i+1幀的讀取並行處理,從而提高實時性

作業與作業排程

批處理系統中的作業

作業

  • 作業,包含了程式,資料以及作業說明書,系統根據說明書對程式的執行進行控制
  • 在批處理系統中,是以作業為基本單位從外存調入記憶體的

作業步

  • 作業執行期間,每個作業需經過一個個相對獨立又相互關聯的順序加工步驟才能得到結果,這些加工步驟稱為作業步
  • 一個典型的作業分成:編譯作業步,連結裝配作業步,執行作業步

作業控制塊(Job Control Block,JCB)

  • 為管理和排程作業,每個作業設定了一個作業控制塊JCB,其中儲存了系統對作業進行管理和排程所需的全部資訊,如:作業標識,使用者名稱稱,使用者賬號,作業型別,作業狀態,排程資訊,資源需求等
  • 每當一個作業進入系統,便由作業註冊程式建立一個JCB,然後進行管理和排程

作業執行的三個階段和三種狀態

  • 收容階段,對應作業的後備狀態,將作業輸入到硬碟,再為其建立JCB,並放入作業後備佇列
  • 執行階段,對應作業的執行狀態,作業被作業排程選中,分配資源建立程序,並放入就緒佇列
  • 完成階段,對應作業的完成狀態,回收JCB和資源,將結果形成輸出檔案輸出

作業排程主要任務

主要任務是根據JCB中的資訊監測資源是否能滿足作業的需求,並按照一定的演算法從外存後備佇列中選取作業進入記憶體,故其又稱接納排程。每次執行作業排程都需做以下決定

  • 接納多少個作業
  • 接納哪些作業

作業排程演算法

  • 先來先服務排程演算法(First-come First-served,FCFS)

    • 最簡單的排程演算法,既可用於作業排程,又能用於程序排程
    • 該演算法按作業到達的時間次序進行排程,即等待時間為優先順序評判的唯一標準。
  • 短作業優先排程演算法(Short Job First,SJF)

    • 既可用於作業排程,又能用於程序排程
    • 該演算法按作業長短排程,即作業執行時間為優先順序評判的唯一標準,時間越短優先順序越高
    • 缺點是:
      1. 必須預知作業多執行時間
      2. 對長作業不利,完全忽視作業等待時間,可能出現飢餓現象
      3. 無法優先處理緊迫作業。
  • 優先順序排程演算法(Priority-scheduling Algorithm,PSA)

    • 該演算法按作業優先順序排程,而作業的優先順序基於作業的緊迫程度
  • 高響應比優先排程演算法

    • 該演算法既考慮作業等待時間,又考慮作業執行時間

    • 該演算法為每個作業引入一個動態優先順序,令它隨等待時間增加而優先順序提高

    $$
    優先權R_p=\frac{等待時間+要求服務時間}{要求服務時間}=\frac{響應時間}{要求服務時間}
    $$

程序排程

程序排程任務

  • 儲存處理機的現場資訊
  • 按某種演算法選取程序
  • 把處理器分配給程序

程序排程機制

  • 排隊器
  • 分派器
  • 上下文切換器

程序排程方式

  • 非搶佔方式
    • 一旦把處理機分配給某個程序,就讓它一直執行直到其完成,不會因為任何原因去搶佔當前正在執行程序的處理機,直至該程序完成或發生某事件而被阻塞,才把處理機分配給其他程序
  • 搶佔方式
    • 排程程式會根據某種原則去暫停某個正在執行的程序,把已分配給該程序的處理機重新分配給其他程序。搶佔不是任意性行為,必須遵循一定的原則:
      • 優先權原則,即允許優先順序高的新程序搶佔當前程序的處理機;
      • 短程序優先原則,即允許新的短程序搶佔當前長程序的處理機;
      • 時間片原則,即各程序按時間片輪轉執行,當正在執行的程序的一個時間片用完後便停止執行並重新排程。

程序排程演算法

  • 輪轉排程演算法(Round Robin,RR)

    • 基本原理:系統把所有就緒程序按FCFS排成一就緒佇列,並讓隊首程序輪流出隊,把CPU分配給出隊程序並讓它執行一個時間片。系統可以設定每隔一定時間產生依次中斷,以啟用排程程式進行重新排程。
    • 程序切換時機
      • 一個時間片用完之前該程序就已經完成時,立即啟用排程程式重新排程,啟動一個新時間片
      • 一個時間片用完時,計時器中斷處理程式會被啟用,此時若程序未完成,則會被送入就緒佇列尾。
    • 時間片大小確定
      • 時間片過短則利於短作業,但會頻繁地進行程序排程和程序上下文切換,增加系統開銷。
      • 時間片過長,極端情況下每個程序都能在一個時間片內完成,RR演算法也就退化成了FCFS演算法。
      • 較可取的時間片長度是略長於一次典型互動所需的時間。
  • 優先順序排程演算法

    輪轉排程演算法其實隱含了一個假設:所有程序的緊迫程度相同,但實際並非如此,所以引入了優先順序

    • 演算法型別
      • 搶佔式優先順序排程演算法
        • 把處理機分配給優先順序最高的程序執行,執行期間若出現另一個優先順序更高的程序,則將處理機分配給新的程序
      • 非搶佔式優先順序排程演算法
        • 一旦把處理機分配給優先順序最高的程序執行,就一直執行下去直到完成,或因該程序發生某事件放棄處理機時,才能重新分配處理機
    • 優先順序型別
      • 靜態優先順序(優先順序數字放於PCB)
      • 動態優先順序
  • 多佇列排程演算法

    • 把就緒佇列拆分為多個,把型別或性質不同的程序分配到不同的就緒佇列佇列,不同的佇列還可以設定不同的優先順序,採用不同的排程演算法。
  • 多級反饋佇列排程演算法

    • 設定多個就緒佇列,佇列的優先順序依次降低,佇列優先順序越高,其對應的時間片越小。通常某佇列的時間片大小是上一佇列的兩倍。
    • 每個佇列都採用FCFS演算法。新程序進入記憶體後首先進入第一個佇列,按FCFS原則等待排程。若程序可以在一個時間片內完成則撤出,否則把它移入下一個佇列隊尾等待排程,以此類推。當程序被降至最後一個佇列時,則採用RR演算法執行。
    • 按佇列優先順序排程,即若要排程第i佇列的程序,則要求第1~(i-1)佇列都空閒。若某佇列的某程序執行時有新的程序進入優先順序更高的佇列,則需立即把該程序放回隊尾,並把處理機分配給新程序。
  • 基於公平原則演算法

    • 保證排程演算法
      • 保證每個程序都獲得同等的處理機時間
    • 公平分享排程演算法
      • 保證每個使用者都獲得同等的處理機時間

實時排程

實時系統存在兩種不同性質的實時任務,即HRT任務和SRT任務,它們都有一個截止時間,為保證系統正常工作,實時排程必須能滿足實時任務對截止時間的要求

實現條件

  • 提供必要資訊
    • 就緒時間,開始截止時間和完成截止時間,處理時間,資源要求,優先順序
  • 系統處理能力強
  • 採用搶佔式排程機制
  • 具有快速切換機制
    • 對中斷的快速響應能力
    • 快速的任務分配能力

實時排程演算法的分類

  • 根據實時任務性質,可分為硬實時排程演算法和軟實時排程演算法

  • 按排程方式可分為

    • 非搶佔式排程演算法
      • 非搶佔式輪換排程演算法
      • 非搶佔式優先排程演算法
    • 搶佔式排程演算法
      • 基於時鐘中斷的搶佔式優先順序排程演算法
      • 立即搶佔的優先順序排程演算法

  • 最早截止時間優先(Earliest Deadline First,EDF)演算法

    • 根據任務的截止時間確定優先順序,截止時間越早,在佇列的位置越靠前,排程程式總是選擇隊首程序執行。
  • 最低鬆弛度優先(Least Laxity First,LLF)演算法

    • 根據任務的緊急(鬆弛)程度確定優先順序,緊急程度則根據必須完成時間、執行時間和當前時間綜合考量

    • 假設一個任務必須在時刻200ms時完成,而執行這個任務需要100ms,則這個任務在0時刻的緊急程度就是100ms,在100ms時刻的緊急程度為0(此時再不執行則無法按時完成)。鬆弛度的計算為:
      $$
      鬆弛度=必須完成時間−本身執行時間−當前時間
      $$

優先順序倒置

  • 形成:由於執行順序不同,可能高優先順序程序/執行緒被低優先順序程序/執行緒延遲或阻塞

  • 例:P1和P3通過共享一個臨界資源進行互動,優先順序P1>P2>P3

  • 解決辦法:

    • 簡單方法:規定程序進入臨界區後不能被搶佔處理機
    • 實用方法:建立在動態優先順序繼承基礎上,當優先順序更高的程序或執行緒B進入相同臨界區,原來已經進入臨界區的相對優先順序低的程序A繼承這個B的更高優先順序,直到退出臨界區

死鎖

資源問題

  • 可重用性資源(訊號量)和可消耗性資源
  • 可搶佔式資源和不可搶佔式資源(訊號量)

死鎖成因

  • 競爭不可搶佔資源
  • 競爭可消耗資源
  • 程序推進順序不當。

定義:每個程序都在等待

死鎖定義

一組程序中的每個程序都在等待僅由該組程序中的其他程序才能引發的事件,則該組程序是死鎖的

死鎖產生必要條件

無法同時滿足這四個條件就不會產生死鎖

  1. 互斥條件:待分配的資源的使用具有排他性
  2. 請求和保持條件:若程序持有了一個資源的同時又有一個新的資源請求,且該資源已被其他程序佔有,此時請求程序被阻塞而已持有的資源又繼續保持;
  3. 不可搶佔條件:程序獲得的資源在使用完之前不能被搶佔,只能在程序使用完時自己釋放
  4. 迴圈等待條件:存在一個程序——資源的迴圈鏈,構成環路等待

處理死鎖方法

四種防範程度逐漸減弱

  1. 預防死鎖

    提前破壞死鎖的必要條件(任意一個)

  2. 避免死鎖

  3. 檢測死鎖

  4. 解除死鎖

預防死鎖

破壞請求和保持條件

  1. 第一種協議

    所有程序在開始執行之前,必須一次性地獲取整個執行過程中所需的全部資源

  2. 第二種協議

    允許一個程序獲得初期資源便可開始執行,由於會釋放已經用過的資源所以不會死鎖

破壞不可搶佔條件

當一個已經保持了某些不可被搶佔資源的程序,提出新的資源請求而不能得到滿足時,它必須釋放已經保持的所有資源,待以後需要時再重新申請

破壞迴圈等待條件

對系統所有資源型別進行線性排序,並賦予不同序號,規定每個程序必須按序號遞增的順序請求資源

避免死鎖

把系統狀態分為安全狀態和不安全狀態。

在系統進行資源分配前,先計算系統能否按照某種程序推進順序分配資源,從而滿足每個程序對資源的需求,若可以,則可找到安全序列,稱系統處於安全狀態

若找不到這樣一個安全序列,則稱系統處於不安全狀態

銀行家演算法

這個演算法是最有代表性的避免死鎖演算法,由Dijkstra提出。銀行家演算法要求每一個新程序進入系統時都必須申明執行時所需的各種資源的最大數目,且不能超過對應的系統擁有總量,同時要求系統維護四個資料結構:

  1. 一個m維向量Available,Available[j]=K表示系統中第j類資源的當前可用數目為K,顯然該向量的初始值為系統全部資源的可用數目;
  2. 一個n×m的矩陣Max,Max[i][j]=K表示程序i對第j類資源的最大需求數目為K;
  3. 一個n×m的矩陣Allocation,Allocation[i][j]=K表示程序i當前已分得的第j類資源數目為K;
  4. 一個n×m的矩陣Need,Need[i][j]=K表示程序i還需要第j類資源K個才能完成任務

顯然Max[i][j]=Need[i][j]+Allocation[i][j]

有了這些資料結構,就可以進行安全性檢查了。對於到來的程序Pi,設它對資源的請求向量為Requesti,Requesti[j]=KRequesti[j]=K表示該程序對第j類資源的需求量為K,接下來開始執行檢查:

  1. Requesti[j]≤Need[i][j],則進行下一步,否則認為出錯,因為這代表它請求的資源數大於它所需要的資源數;

  2. Requesti[j]≤Available[j],則進行下一步,否則令程序等待,因為此時資源不足以保證程序的執行;

  3. 系統修改資料結構的值(即模擬資源分配):

    Available[j]=Available[j]−Request[i][j]

    Allocation[i][j]=Allocation[i][j]+Requesti[j]

    Need[i][j]=Need[i][j]−Requesti[j]

死鎖的檢測與解除

系統應當提供兩個演算法:

  1. 死鎖檢測演算法。該方法用於檢測系統狀態,以確定系統中是否發生了死鎖。

    1. 資源分配圖,圓圈代表程序,方框代表一類資源,邊代表請求/分配

    2. 死鎖原理:當且僅當S狀態的資源分配圖是不可完全簡化的,則S為死鎖狀態

      化簡方法:可以找出所有既不阻塞也非獨立的程序結點,然後同時去掉與它相連的所有請求邊和分配邊(即使之孤立)。若所有的程序都可以順利執行,那麼圖中的所有邊都應被消去,即最終資源分配圖是可以被完全簡化的

  2. 死鎖解除演算法:當認定系統中已發生了死鎖,利用該演算法可將系統從死鎖狀態中解脫出來。

    1. 搶佔資源,即掠奪其他程序的資源給死鎖程序;
    2. 終止程序,即終止系統中若干個死鎖程序以打破環路。