即時組排程

0. 警告

擺弄這些設定可能會導致系統不穩定,這些旋鈕僅供 root 使用者使用,並且假定 root 使用者知道自己在做什麼。

最值得注意的是

  • sched_rt_period_us 中非常小的值可能會導致系統不穩定,因為該週期小於可用的 hrtimer 解析度或處理預算重新整理本身所需的時間。

  • sched_rt_runtime_us 中非常小的值可能會導致系統不穩定,因為執行時太短,系統難以取得進展(注意:遷移執行緒和 kstopmachine 都是即時程序)。

1. 概述

1.1 問題

即時排程的關鍵在於確定性,一個組必須能夠依賴於頻寬量(例如,CPU 時間)是恆定的。為了排程多個即時任務組,每個組必須分配一部分可用的 CPU 時間。如果沒有最低保證,即時組顯然會不足。模糊的上限是沒有用的,因為它不能被依賴。這隻給我們留下了一個固定的部分。

1.2 解決方案

CPU 時間是透過指定在給定週期內可以花費多少時間來劃分的。我們為每個即時組分配這個“執行時”,其他即時組不允許使用它。

未分配給即時組的任何時間將用於執行正常優先順序的任務 (SCHED_OTHER)。任何未使用的已分配執行時也將被 SCHED_OTHER 拾取。

讓我們考慮一個例子:一個幀固定的即時渲染器必須每秒傳送 25 幀,這產生了每幀 0.04 秒的週期。現在假設它還必須播放一些音樂並響應輸入,使其大約 80% 的 CPU 時間專用於圖形。然後我們可以給這個組一個 0.8 * 0.04 秒 = 0.032 秒的執行時。

這樣,圖形組將有一個 0.04 秒的週期,執行時限制為 0.032 秒。現在,如果音訊執行緒需要每 0.005 秒重新填充 DMA 緩衝區,但只需要大約 3% 的 CPU 時間,則可以使用 0.03 * 0.005 秒 = 0.00015 秒。因此,可以排程該組,週期為 0.005 秒,執行時為 0.00015 秒。

剩餘的 CPU 時間將用於使用者輸入和其他任務。由於即時任務已明確分配執行任務所需的 CPU 時間,因此可以消除圖形或音訊中的緩衝區欠載。

注意:上面的例子尚未完全實現。我們仍然缺少 EDF 排程器來使非統一週期可用。

2. 介面

2.1 系統範圍設定

系統範圍的設定在 /proc 虛擬檔案系統下配置

/proc/sys/kernel/sched_rt_period_us

相當於 100% CPU 頻寬的排程週期。

/proc/sys/kernel/sched_rt_runtime_us

即時排程可能使用的總時間限制。這總是小於或等於 period_us,因為它表示從 period_us 分配給即時任務的時間。如果未啟用 CONFIG_RT_GROUP_SCHED,這僅用於截止日期任務的准入控制。使用 CONFIG_RT_GROUP_SCHED=y,它還表示所有即時組可用的總頻寬。

  • 時間以 us 為單位指定,因為介面是 s32。這給出了從 1us 到大約 35 分鐘的執行範圍。

  • sched_rt_period_us 的取值範圍為 1 到 INT_MAX。

  • sched_rt_runtime_us 的取值範圍為 -1 到 sched_rt_period_us。

  • 執行時為 -1 指定 runtime == period,即沒有限制。

  • sched_rt_runtime_us/sched_rt_period_us > 0.05,以便為公平的 dl_server 保留頻寬。要獲得準確的值,請檢查 /sys/kernel/debug/sched/fair_server/cpuX/ 中 runtime/period 的平均值。

2.2 預設行為

sched_rt_period_us(1000000 或 1s)和 sched_rt_runtime_us(950000 或 0.95s)的預設值。這給 SCHED_OTHER(非 RT 任務)使用了 0.05 秒。選擇這些預設值是為了讓失控的即時任務不會鎖定機器,而是留出一點時間來恢復它。透過將執行時設定為 -1,您將獲得舊的行為。

預設情況下,所有頻寬都分配給根組,新組從 /proc/sys/kernel/sched_rt_period_us 獲取週期,執行時為 0。如果要將頻寬分配給另一個組,請減少根組的頻寬,並將部分或全部差額分配給另一個組。

即時組排程意味著您必須在組接受即時任務之前將總 CPU 頻寬的一部分分配給該組。因此,即使該使用者有權以即時優先順序執行程序,在您完成該操作之前,您也無法以 root 以外的任何使用者身份執行即時任務!

2.3 任務分組的基礎

啟用 CONFIG_RT_GROUP_SCHED 允許您將真實的 CPU 頻寬顯式分配給任務組。

這使用 cgroup 虛擬檔案系統和 "<cgroup>/cpu.rt_runtime_us" 來控制為每個控制組保留的 CPU 時間。

有關使用控制組的更多資訊,您還應該閱讀 控制組

組設定根據以下限制進行檢查,以使配置可排程

Sum_{i} runtime_{i} / global_period <= global_runtime / global_period

目前,這可以簡化為以下內容(但請參閱未來計劃)

Sum_{i} runtime_{i} <= global_runtime

3. 未來計劃

目前正在進行工作,以使每個組的排程週期(“<cgroup>/cpu.rt_period_us”)也可配置。

週期的約束是子組必須具有小於或等於其父組的週期。但實際上,它_目前_不是很實用,因為它容易在沒有截止日期排程的情況下被餓死。

考慮兩個兄弟組 A 和 B;兩者都具有 50% 的頻寬,但 A 的週期是 B 的兩倍。

  • 組 A:週期=100000us,執行時=50000us

    • 這每 0.1 秒執行一次 0.05 秒

  • 組 B:週期= 50000us,執行時=25000us

    • 這每 0.1 秒執行兩次 0.025 秒(或每 0.05 秒一次)。

這意味著目前 A 中的 while (1) 迴圈將在 B 的整個週期內執行,並且可能會使 B 的任務(假設它們具有較低的優先順序)在整個週期內被餓死。

下一個專案將是 SCHED_EDF(最早截止日期優先排程),以將完整的截止日期排程帶到 linux 核心。截止日期排程上述組並將週期結束視為截止日期將確保它們都獲得分配的時間。

實現 SCHED_EDF 可能需要一段時間才能完成。優先順序繼承是最大的挑戰,因為當前的 linux PI 基礎設施適用於有限的靜態優先順序級別 0-99。對於截止日期排程,您需要進行截止日期繼承(因為優先順序與截止日期增量(截止日期 - 現在)成反比)。

這意味著必須重做整個 PI 機制 - 這是我們擁有的最複雜的程式碼之一。