簡析 Linux 的 CPU 時間( 二 )


Linux 的調度策略是搶占式的,每個線程都有優先級prirority的概念,并按照優先級高低分為兩種:

  • 實時進程(優先級 0~99)
  • 普通進程(優先級 100~139)
每個 CPU 都有自己的運行隊列 runqueue,需要運行的線程會被加入到這個隊列中 。
簡析 Linux 的 CPU 時間

文章插圖
每個隊列可以進一步細分為 3 個隊列以及 5 種調度策略:
  • dl_rq
    • SCHED_DEADLINE 選擇 deadline 距離當前時間點最近的任務執行
  • rt_rq —— 可以互相搶占的實時任務
    • SCHED_FIFO 一旦搶占到 CPU 資源,就會一直運行直到退出 , 除非被高優先級搶占
    • SCHED_RR 當 CPU 時間片用完,內核會把它放到隊列末尾,可以被高優先級搶占
  • cfs_rq —— 公平占用 CPU 時間的普通任務
    • SCHED_NORMAL 普通進程
    • SCHED_BATCH 后臺進程
Linux 內核在選擇下一個任務執行時,會按照該順序來進行選擇 , 也就是先從 dl_rq 里選擇任務,然后從 rt_rq 里選擇任務,最后從 cfs_rq 里選擇任務 。所以實時任務總是會比普通任務先得到執行 。
實時進程的優先級總是高于普通進程,因此當系統中有實時進程運行時 , 普通進程幾乎是無法分到時間片的 。
nice 值為了保證 cfs_rq 隊列的公平性,Linux 采用完全公平調度算法 CFS Completely Fair Scheduler進行調度,保證每個普通進程都盡可能被調度到 。
CFS 引入了 vruntime 作為衡量是否公平的依據:
  • vruntime 與任務占用的 CPU 時間成正比
  • vruntime 與任務優先級成反比(優先級越高vruntime增長越慢)
如果一個任務的 vruntime 較小,說明它以前占用 CPU 的時間較短,受到了不公平對待 , 因此該進程會被優先調度,從而到達所謂的公平性 。
為了實現可控的調度,Linux 為普通進程引入了 nice 值的概念 。其的取值其范圍是 -20 ~ +19,調整該值會改變進程的優先級:prirority += nice 。
與此同時 vruntime 計算也會受到影響:
進程的 nice 值越小, 優先級越高, 所能分到的運行時間也越多當用戶進程設置了一個大于 0 的 nice 值時,其用戶態的運行時間將被統計為nice time 而不是 user time 。簡單來說,nice time 表示 CPU 花了多少時間用于運行低優先級的任務 。
nice time 占比比較高時,通常是某些定時任務調度器導致的:它們會為后臺任務進程設置一個較大的 nice 值,避免這些進程與其他線程爭搶 CPU 資源 。
軟中斷中斷就是一種插隊機制,可以讓操作系統優先處理一些緊急的任務 。當硬件設備(例如 , 網卡)需要向 CPU 發出信號時(例如,數據已到達),就會產生硬件中斷 。
CPU 接收到中斷時 , 會切換到內核態執行特定的中斷服務,并且期間不允許其他中斷搶占(關中斷) 。當中斷服務需要執行較長時間時,可能會導致且其他的中斷得不到及時的響應 。
為了提高中斷處理效率,操作系統在之前的基礎上把中斷處理分成兩部分:
  • 上半部top half:在屏蔽中斷的上下文中運行,用于完成關鍵性的處理動作
  • 下半部bottom half:不在中斷服務上下文中執行 , 主要處理不那么急迫但耗時的任務
內核在處理完中斷上半部后,可以延期執行下半部 , 該機制被稱為軟中斷softirq 。軟中斷處理的過程是不會關中斷的,因此當有硬中斷到來的時候,可以及時響應 。
構成軟中斷機制的核心元素包括:
  • 注冊: 軟中斷狀態寄存器 irq_stat
  • 處理: 軟中斷向量表 softirq_vec
  • 觸發: 軟中斷守護線程 daemon

簡析 Linux 的 CPU 時間

文章插圖
  1. 調用open_softirq()將軟中斷服務程序注冊到軟中斷向量表softirq_vec(可?。?
  2. 調用raise_softirq()觸發軟中斷事務