2016年2月4日 星期四

Linux CPU 排程

Linux 程式執行以 thread 為單位,決定誰取得 CPU 使用權稱排程。Thread 在 userspace 是 preemptible 的 (非 cooperative multitasking),任何時間點 kernel tick 都有可能會中斷程式並切換到其它 thread,一個無限迴圈並不會卡住整個系統。至於透過 syscall 進入 kernel 的階段,是否 preemptible 由 kernel 設定 CONFIG_PREEMPT 決定。在 non-preemptive kernel,無限迴圈是會卡住整個系統。

註:preempty 是一種插隊的行為,像救護車,可翻作...。

由於 thread 是 preemptive 的,同一 process 內不同 thread 共用的資料,可能修改到一半有其它 thread 存取而造成錯誤 (修改被覆蓋、資料結構破壞等),所以需要 mutex 保護。函式可能重複呼叫,要看是否可以 reentry

每個 thread 有各自的 policy 及 priority 來決定排程,都會 preemptive 執行 priority 值最大的,相同 priority 的再由 policy 安排如何執行。thread 建立時會繼承 policy 及 priority。

等級policypriority說明
一般SCHED_OTHER
(預設)
0參考 nice 值動態調整 CPU 時間的使用比例,讓每個 thread 輪流、不用等候太久都能分配到 CPU 時間,滿足互動式多工系統。
SCHED_BATCH2.6.16+。類似 SCHED_OTHER,但排程會減少喚醒次數來減少 thread 切換,一般用在非互動式的程式。
SCHED_IDLE2.6.23+。以最低優先權執行。
(soft) real timeSCHED_FIFO1~99一開始先插隊執行,之後次序照先後排隊。每次執行直到等待 IO 或讓出。
SCHED_RR同 SCHED_FIFO,但每次執行有 time slice 時間限制。
SCHED_DEADLINELinux 3.14+

nice 值 (在 POSIX 是 process 層級的屬性,但目前 Linux/NPTL 實作是 thread 層級的屬性。)

  • 範圍 -20 ~ 19,預設 0,值越大越「好心」,排程分配的份量越少。對應到 kernel 內部表示的範圍是 40 ~ 1,相當於 20 - nice 值。不同 kernel 版本排程演算法有所不同。
  • 可以提高自己的 nice 值,只有 privileged thread 才能降低或設為負值 (chap35.3.2)。自從 Linux 2.6.12,process 有適當的 RLIMIT_NICE 軟性限制 (見 getrlimit()) 可以降低 nice 值。
  • round-robin timing-sharing 的 CPU 時間分配,滿足互動式多工系統需要的 Fairness (公平) 和 Responsive (不用等太久),按順序都會分配到 (不會餓死) time slice 或 quantum 的時間,除非自願放棄 (休息或等候) 才會縮短。
  • 會繼承
  • Linux 2.6.38 新增 "autogroup" 功能代表 nice 值在許多 circumstances 不再有其傳統效果。
  • getpriority(which, who):取得 which 中 who 裡 nice 值最小的。
    • which 可以是 PRIO_PROCESS (指 thread)、PRIO_PGRP、或 PRIO_USER,決定 who 是 process ID、process group ID、或 user ID。who 為 0 表示本身所屬 process、process group、或 user。
    • 由於 -1 可能是有效的值或錯誤,需先設 errno 為 0,如果回傳值是 -1 時,需檢查 errno 判別。
  • setpriority(which, who, value):
    • 有 CAP_SYS_NICE 權限可設其它 thread nice 值
    • 沒權限只能增加符合 real 或 effective user ID 的 thread。Kernel v2.6.12+ 的 RLIMI_NICE 限定可設定的範圍。
  • nice(incr)
  • 指令 nice
  • 指令 renice
POSIX realtime scheduling API 決定排程 policy 和 priority => 更緊密控制 CPU 時間
CPU affinity mask => 在多處理器系統決定可使用哪些處理器。
註:sched_get_priority_min(policy) 及 sched_get_priority_max(policy) 取得特定 policy 的 priority 範圍。
註:sched_setscheduler() 設定 pid 或自己的 policy 及 priority,而sched_setparam() 只設定 priority。sched_getscheduler()、sched_getparam() 分別取得 policy 和 prioity。在 2.6.12 以前, CAP_SYS_NICE 的 process 才能設定 policy 和 priority。另外,SCHED_OTHER process 的 real/effective user ID 和我的effective user ID 相同的,也可以設定。2.6.12 之後新增 RLIMIT_RTPRIO...。
s
避免 realtime process locking up 整個系統
  • 用 setrlimit() 設定適合的 low soft CPU time resource limit (RLIMIT_CPU, described in Section 36.3),如果 consumes too much CPU time 會送 SIGXCPU signal,預設 kill the process。
  • 用 alarm() 設定 alarm timer,如果執行超過時間會 killed by a SIGALRM signal。
  • 建立 watchdog process 執行在較高 realtime priority,無限迴圈 sleep 一段時間檢查其它 process 狀態,可順便量測 CPU time (Section 23.5.3 的 clock_getcpuclockid()) 和檢查 policy 和 priority,可降低 priority 或送 signal 停止會結束它。
  • 2.6.25 開始提供 RLIMIT_RTTIME 限制一次持續 CPU time 用量,送 signal SIGXCPU。細節見 Documentation/ scheduler/sched-rt-group.txt。
SCHED_RESET_ON_FORK
sched_yield()
註:sched_rr_get_interval() 取得 SCHED_RR 每次執行時間。
註:2.6.25+ /proc/sys/kernel/sched_rt_period_us/proc/sys/kernel/sched_rt_runtime_u

參考來源:
  1. man sched
  2. :《The Linux Programming Interface》chap. 35
  3. http://fcamel-life.blogspot.tw/2012/02/linux-process-priorities-and-scheduling.html (整理得不錯)
  4. http://stackoverflow.com/questions/10287561/sched-fifo-thread-is-preempted-by-sched-other-thread-in-linux
  5. man setpriority 
20200713 最後更新

沒有留言:

張貼留言

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...