Linux內核分析第八週總結

第八章 進程的切換和系統的通常執行過程

進程調度與進程調度的時機分析

第一種分類:

  • I/O密集型(I/O-bound):頻繁的進行I/O,一般會花費不少時間等待I/O操做的完成
  • CPU密集型(CPU-bound):計算密集型,須要大量的CPU時間進行運算linux

    第二種分類:

  • 批處理進程:沒必要與用戶交互,一般在後臺運行,沒必要很快響應。主要用於編譯程序,科學計算
  • 交互式進程:須要常常與用戶交互,因此要花不少時間等待用戶輸入操做,響應時間要快,平均延遲低於50~150ms。主要用於shell,文本編輯程序,圖形應用程序
  • 實時進程:有實時需求,不該被低優先級的進程阻塞,響應時間要短要穩定。主要用於視頻、音配、機械控制。算法

不一樣的進程要採起不一樣的進程調度策略

調度策略:是一組規則,它們決定何時以怎樣的方式選擇一個新進程運行shell

Linux的調度基於分時和優先級策略:架構

  • 進程根據優先級(系統根據特定算法計算出來)排隊;
  • 這個優先級的值表示如何適當分配CPU;
  • 調度程序會根據進程的運行週期動態調整優先級;較長時間未分配到CPU的進程,一般提高優先級,已經在CPU上運行了較長時間的進程,一般下降優先級

調度策略本質上是一種算法,這些算法從實現的角度看僅僅是從運行隊列中選擇一個新進程,選擇的過程當中運用了不一樣的策略而已框架

進程的調度時機

  • 中斷處理過程(包括時鐘中斷、I/O中斷、系統調用和異常)中,直接調用schedule(),或者返回用戶態時根據need_resched標記調用schedule()
  • 內核線程能夠直接調用schedule()進行進程切換,也能夠在中斷處理過程當中進行調度,也就是說內核線程做爲一類的特殊的進程能夠主動調度,也能夠被動調度
  • 用戶態進程沒法實現主動調度,僅能經過陷入內核態後的某個時機點進行調度,即在中斷處理過程當中進行調度
  • 用戶態進程只能被動調度,內核線程是隻有內核態沒有用戶態的特殊進程。函數

    進程切換上下文的相關代碼

  • 爲了控制進程的執行,內核必須有能力掛起正在CPU上執行的進程,並恢復之前掛起的某個進程的執行,這叫作進程切換、任務切換、上下文切換。
  • 掛起正在CPU上執行的進程,與中斷時保存現場是不一樣的,中斷先後是在同一個進程上下文中,只是由用戶態轉向內核態執行,可是是同一個進程,而進程上下文的切換是兩個進程在切換。
  • 進程上下文包含了進程執行須要的全部信息:用戶地址空間:包括程序代碼,數據,用戶堆棧等、控制信息:進程描述符,內核堆棧等
    硬件上下文(中斷也要保存硬件上下文只是保存的方法不一樣,中斷是經過壓棧來解決的,而這裏是經過schedule函數)
  • schedule()函數選擇一個新的進程來運行,並調用context_switch進行上下文的切換,這個宏調用switch_to來進行關鍵上下文切換
  • next = pick_next_task(rq, prev);//進程調度算法都封裝這個函數內部
  • context_switch(rq, prev, next)來完成進程上下文切換
  • switch_to利用了prev和next兩個參數:prev指向當前進程,next指向被調度的進程操作系統

Linux系統的通常執行過程

Linux系統的通常執行過程分析

最通常的狀況:正在運行的用戶態進程X切換到運行用戶態進程Y的過程線程

  • 正在運行的用戶態進程X
  • 發生中斷
  • 進入內核代碼,SAVE_ALL //保存現場
  • 中斷處理過程當中或中斷返回前調用了schedule(),其中的switch_to作了關鍵的進程上下文切換
  • 標號1以後開始運行用戶態進程Y(這裏Y曾經經過以上步驟被切換出去過所以能夠從標號1繼續執行)
  • restore_all //恢復現場
  • iret - pop cs:eip/ss:esp/eflags from kernel stack
  • 繼續運行用戶態進程Y

關鍵點:中斷和中斷返回中有CPU上下文的切換,進程調度的過程當中有進程上下文的切換,此時切換了兩個進程間的堆棧3d

linux系統執行過程當中的幾個特殊狀況:

  • 經過中斷處理過程當中的調度時機,用戶態進程與內核線程之間互相切換和內核線程之間互相切換,與最通常的狀況很是相似,只是內核線程運行過程當中發生中斷沒有進程用戶態和內核態的轉換;
  • 內核線程主動調用schedule(),只有進程上下文的切換,沒有發生中斷上下文的切換,與最通常的狀況略簡略;
  • 建立子進程的系統調用在子進程中的執行起點及返回用戶態,如fork;(若是下一個進程是還沒有被調用過的進程,它的執行的起點是ret_from_fork,nexp_ip=ret_from_fork)
  • 加載一個新的可執行程序後返回到用戶態的狀況,如execve;(修改中斷時保存的信息)

X86下的地址空間有4G,0~3G用戶態、內核態能夠訪問,3G以上只有內核態能夠訪問
內核是全部進程共享的。內核至關於出租車,進程至關於客人,對全部進程都同樣。沒有進程須要「承載」的時候,內核進入idle0號進程進行「空轉」
內核是各類中斷處理過程和內核線程的集合rest

Linux系統架構和執行過程概覽

Linux操做系統架構概覽

最簡單、最複雜的操做——執行ls命令:

從CPU和內存的角度看Linux系統的執行:

  • 從CPU角度看:一個進程調度:等待鍵盤輸入的時候,cpu會切換到其餘進程,同時在進行等待:由於輸入鍵盤會產生I/O中斷,再調度回來
  • 從內存角度看:全部的物理地址都會被映射到3G以上的地址空間:由於這部分對全部進程來講都是共享的

實驗


完成跟蹤

總結:

linux調度的核心函數爲schedule,schedule函數封裝了內核調度的框架。細節實現上調用具體的調度類中的函數實現。當切換進程已經選好後,就開始用戶虛擬空間的處理,而後就是進程的切換switch_to()。所謂進程的切換主要就是堆棧的切換,這是由宏操做switch_to()完成的。並且知道schedule中調用next = pick_next_task(rq, prev);實行進程調度算法,其後調用context_switch(rq, prev, next);進行進程上下文切換,其中context_switch(rq, prev, next)中的宏switch_to起着關鍵做用。

相關文章
相關標籤/搜索