天天看點

Linux核心第八節 20135332武西垚

第一種分類:

  • I/O-bound:頻繁進行I/O,并且需要花費很多時間等待I/O完成
  • CPU-bound:計算密集,需要大量的CPU時間進行運算

第二種分類:

  • 批處理程序:不必與使用者互動,常在背景進行;不必很快響應(典型的批處理系統:編譯程式、科學計算)。
  • 實時程序:有實時需求,不應被低優先級程序阻塞,響應時間短、要穩定(典型的實時程序:視訊/音頻、機械控制等)。
  • 互動式程序:需要經常與使用者互動,是以要花很多時間等待使用者輸入操作,響應時間要快,平均延遲要低(典型的互動式程式:shell、文本編輯程式、圖形應用程式)。
Linux中的程序排程

排程政策:是決定什麼時候以怎樣的方式選擇一個新程序運作的規則。Linux中的排程是多種政策和排程算法的組合。

Linux既支援普通的分是程序。也支援實時程序。Linux的排程基于分時和優先級。

Linux根據程序的優先級進行排隊

  • 根據特定的算法計算出程序的優先級,用一個值表示,這個值表示把程序如何适當的配置設定給CPU。
  • Linux中程序的優先級是動态的,排程程式會根據程序行為的周期性調整程序的優先級。(較長時間未配置設定到CPU的程序優先級升高,已在CPU上運作了較長時間的程序優先級下降)

核心中的排程算法相關代碼使用了類似OOD中的政策模式,這些算法從實作的角度看僅僅是從運作隊列中選擇一個新程序,選擇的過程中運用了不同的政策而已。不需要了解這種政策,對我們對于核心的了解并沒有幫助。對于了解作業系統的工作機制,反而是程序的排程時機與程序的切換機制更為關鍵。

schedule函數

schedule函數:實作排程,在隊列中自傲一個程序把CPU配置設定給它。

調用方法:

  • 直接調用schedule()
  • 松散調用,根據need_resched标記
程序排程的時機
  • 中斷處理過程(包括時鐘中斷、I/O中斷、系統調用和異常)中,直接調用schedule(),或者傳回使用者态時根據need_resched标記調用schedule()。
  • 核心線程可以直接調用schedule()進行程序切換,也可以在中斷處理過程中進行排程,也就是說核心線程作為一類的特殊的程序可以主動排程,也可以被動排程(核心線程是隻有核心态而沒有使用者态的特殊程序)。
  • 使用者态程序隻能被動排程,僅能通過陷入核心态後的某個時機點進行排程,即在中斷處理過程中進行排程。

程序上下文切換相關代碼分析

程序的切換

程序切換(任務切換、上下文切換):為了控制程序的執行,核心必須有能力挂起正在CPU上執行的程序,并恢複以前挂起的某個程序的執行,

挂起正在CPU上執行的程序,與中斷時儲存現場是不同的,中斷前後是在同一個程序上下文中,隻是由使用者态轉向核心态執行;而程序切換是在不同的程序之間進行排程。

程序上下文包含了程序執行需要的所有資訊

  • 使用者位址空間:包括程式代碼,資料,使用者堆棧等
  • 控制資訊:程序描述符,核心堆棧等
  • 硬體上下文(注意中斷也要儲存硬體上下文隻是儲存的方法不同,中斷:儲存現場&恢複線程;程序排程:switc_to的機制)
schedule()函數實作方法

schedule()函數選擇一個新的程序來運作,并調用context _ switch進行上下文的切換,這個宏調用switch _ to來進行關鍵上下文切換

  • next = pick _ next _ task(rq, prev);//封裝了使用的某種程序排程政策,選擇一個程序作為next
  • context_switch(rq, prev, next);//實作程序上下文切換
  • switch_to切換寄存器的狀态和堆棧,利用兩個參數:prev指向目前程序,next指向被排程的程序
  • 一般程序切換的過程

    正在運作的使用者态程序X切換到運作使用者态程序Y的過程:
    1. 正在運作的使用者态程序X
    2. 發生中斷——save cs:eip/esp/eflags(目前程序CPU的狀态壓入使用者态程序X的核心堆棧) load cs:eipss:esp(加載中斷服務例程和核心堆棧)。
    3. 進入中斷處理程序,首先SAVE_ALL,儲存現場
    4. 中斷處理過程中或中斷傳回前調用了schedule(),其中的switch_to做了關鍵的程序上下文切換
    5. 标号1之後開始運作使用者态程序Y(這裡Y曾經通過以上步驟被切換出去過是以可以從标号1繼續執行)
    6. restore_all 恢複程序X的執行狀态
    7. iret - pop cs:eip/ss:esp/eflags from kernel stack
    8. 繼續運作使用者态程序Y

    幾種特殊情況

    • 通過中斷處理過程中的排程時機,使用者态程序與核心線程之間互相切換和核心線程之間互相切換,與最一般的情況非常類似,隻是核心線程運作過程中發生中斷沒有程序使用者态和核心态的轉換;
    • 核心線程主動調用schedule(),隻有程序上下文的切換,沒有發生中斷上下文的切換,比 最一般的情況略簡略;
    • 建立子程序的系統調用在子程序中的執行起點及傳回使用者态,如fork;
    • 加載一個新的可執行程式後傳回到使用者态的情況,如execve;