2009年1月30日 星期五

Linux 的 Real-time 排程支援

Standard
POSIX.1b 定義了一系列的系統呼叫,去提供即時(Real-time)需求的支援,實作細節和實際效能則由各作業系統自行負責。當然,Linux 也依循了這標準,讓各個 Process 有能力的在有限度的範圍內,調整自己的在系統上排程。這裡所講,並不只是一般常見的系統優先權機制,而是建構在其之上的進階排程實作。

首先,可以從 sched_getscheduler(pid_t pid) 的回傳值中,取得目前程式的排程方法,有助於了解當前的排程情形,其可能回傳值如下:
  • SCHED_OTHER
  • SCHED_FIFO
  • SCHED_RR
  • SCHED_BATCH

範例原始碼(sched_policy.c):
#include <stdio.h>
#include <sched.h>

const char *sched_policy[] = {
"SCHED_OTHER",
"SCHED_FIFO",
"SCHED_RR",
"SCHED_BATCH"
};

int main(int argc, char *argv[])
{
printf("Scheduler Policy is %s.\n", sched_policy[sched_getscheduler(0)]);
return 0;
}

Compiling it:
gcc sched_policy.c -o sched_policy

Results:
Scheduler Policy is SCHED_OTHER

標準預設的排程方法是 SCHED_OTHER,意味 Kernel 並不會為這些一般性 Process 做特別的即時排程處理。因為,我們所寫的程式,都沒有被特殊設定,所得到的將都會是使用 SCHED_OTHER。

值得探討的是 SCHED_FIFO 和 SCHED_RR,這是為即時(Real-time)需求所設計的兩種排程類型,在運作規則上,其實兩者是同樣的東西,只是 SCHED_RR 擁有時段分配的制約機制。

SCHED_FIFO(First In-First Out)

SCHED_FIFO 顧名思義就是『先進先出(First In First Out)』,一但 Procees 是 FIFO 模式,在被 Kernel 的排程器設為可運行時,將會立即先佔並插隊執行,比同樣系統優先權的其他『一般 Process』還優先,除非有系統優先權比較高的 Process 正在佔用時間,否則 FIFO Process 通常都會優先佔用。

另外,FIFO Process若是使用 sched_yield() 或是遭暫停而讓出CPU時間,將會被重新排在當時同優先權的最後,等待其他同優先權的 Process 完畢後,再度被運行。所以 SCHED_FIFO ,永遠會有最大的機會被先執行。

SCHED_RR(Round-robin)

而被設定為 SCHED_RR 的 Process,基本上排程行為和 SCHED_FIFO 一樣,不同的是 Process 將被 Kernel 分配一個 timeslice 去限制時間,時間一但用盡,將會被暫停以讓出 CPU。

SCHED_BATCH

大部份排程方法都是被 POSIX 所定義,唯『SCHED_BATCH』是 Linux 獨有的,被實作於 Linux Kernel 2.6.16 之後。被設定 SCHED_BATCH 的 Process,將會在系統沒有其他可運行的 Process 時(Idle),才會被執行,而且不被優先權所影響而導致 Process 提前執行。

至於如何設定排程方法,可這樣實作:
struct sched_param sp = {
.sched_priority = 1
};

sched_setscheduler(0, SCHED_FIFO, &sp);

一般來說,如何去調度 Process ,都是由 Kernel 全權處理,對於撰寫應用程式的開發者來說,除非是有特殊需求,不然不用去考慮這些排程的問題。本文目的,是針對有這樣額外需求的程式,開發人員可參考系統所提供的呼叫,以對排程器做些特殊的調度。