1. 進程調度
the process scheduler is the component of a kernel that selects which process to run next.
進程調度器須要使 處理器使用率最大化,而且提供 使多個進程併發執行的虛擬
Deciding which processes run, when, and for how long is the process scheduler's fundamental responsibility.
時間片:the scheduler allocates the process a 「slice」 of the processor's time
Linux進程調度算法
CFS( Completely Fair Scheduler):enforce fair access to a resource among contending consumers
2. 時間片
若是時間片過大,那麼 掛起進程 開始執行前的
等待時間過長,這將減少 併發執行的粒度,甚至用戶覺察到延遲
若是時間片太小,那麼 系統在進程之間
切換的時間花銷將很大,時間局部性的優點將喪失
CPU密集型:processes are hungry for CPU time,好比科學計算、數學計算、圖像處理
I/O密集型:spend more time blocked waiting for some resource than executing,often issuing and waiting for file or network I/O, blocking on keyboard input
3. CFS調度
傳統Unix進程調度中,有兩個最基礎的變量:優先級和時間片
CFS引進 fair scheduling 算法,CFS賦予每一個進程必定比例的處理器時間,而不是時間片
開始時,CFS賦予N個進程等同的 1/N 處理器時間,而後權衡每一個進程比例進行動態調整
Processes with the default nice value of zero have a weight of one, so their proportion is unchanged
Processes with a
smaller nice value (higher priority) receive a larger weight, increasing their fraction of the processor
process with a l
arger nice value (lower priority) receive a smaller weight, decreasing their fraction of the processor
爲了肯定每一個進程每次運行的實際時間,CFS needs to divide the proportions into a fixed period
例如:20毫秒,2個相同優先級的進程,則每一個進程賦予相同的權重和處理器時間比例,即每一個進程10毫秒
若是是5個進程,則每一個進程分配4毫秒,若是是200個進程呢?
按照常理應該是 每一個進程分配100微秒,可是因爲 上下文切換開銷巨大,而且 局部性優點喪失,這將嚴重影響系統的吞吐率
這時CFS引入另外一個變量:minimum granularity (最小粒度)
minimum granularity是任一進程運行時間長度的下限,這將保證 上下文切換開銷佔 系統總時間開銷的比例 不會過大
By assigning proportions of the processor and not fixed timeslices,CFS is able to enforce fairness: each process gets its fair share of the processor
4. nice val
processes are assigned priorities that affect how long they run,Unix has historically called these priorities nice values
Legal nice values range from
−20 to 19 inclusive, with a default value of 0,
nice值越大,優先級越低,nice值越小,優先級越高
/* increments a process's nice value by inc and returns the newly updated value */
#include <unistd.h>
int nice (int inc);
Passing 0 for inc is an easy way to obtain the
current nice value
nice函數錯誤時返回-1,可是 新的nice值也可能就是-1,爲了區分 函數錯誤 和 返回nice新值爲-1,則以下使用:
int ret;
errno = 0;
ret = nice (10); /* increase our nice by 10 */
if (ret == −1 && errno != 0)
perror ("nice");
else
printf ("nice value is now %d\n", ret);
獲取/設置優先級:算法
#include <sys/time.h>
#include <sys/resource.h>
int getpriority (int which, int who);
int setpriority (int which, int who, int prio);
/* returns the current process’s priority */
int ret;
ret = getpriority (PRIO_PROCESS, 0);
printf ("nice value is %d\n", ret);
/* sets the priority of all processes in the current process group to 10 */
int ret;
ret = setpriority (PRIO_PGRP, 0, 10);
if (ret == −1)
perror ("setpriority");
5. 處理器關聯
the process scheduler must decide which processes run on each CPU
若是一個進程在一個CPU核上被調度,the process scheduler should aim to schedule it on the same CPU in the future
由於 進程
從一個CPU核遷移到另外一個CPU核的代價是巨大的(主要是緩存影響)
if a process moves to a new CPU and writes new data into memory, the data in the old CPU's cache can become stale
這樣,進程調度器必須在
進程遷移CPU花銷 和
多個CPU負載均衡 之間取得平衡
The Linux scheduler attempts to schedule the same processes on the same processors for as long as possible, migrating a process from one CPU
to another only in situations of extreme load imbalance. This allows the scheduler to minimize the cache effects of migration but still ensure that
all processors in a system are evenly loaded
6. 實時系統
硬實時和軟實時
A hard real-time system requires absolute adherence to operational deadlines
A soft real-time system does not consider over‐running a deadline to be a critical failure
7. Linux實時調度策略
FIFO調度:A FIFO-classed process will continue running so long as no higher-priority process becomes runnable
時間片輪轉:When an RR-classed process exhausts its timeslice, the scheduler moves it to the end of the list of processes at its priority
注意:
這兩種實時調度策略中,若是存在更高優先級的進程,那麼低優先級進程將不會運行
int policy;
/* get our scheduling policy */
policy = sched_getscheduler (0);
switch (policy) {
case SCHED_OTHER:
printf ("Policy is normal\n");
break;
case SCHED_RR:
printf ("Policy is round-robin\n");
break;
case SCHED_FIFO:
printf ("Policy is first-in, first-out\n");
break;
case -1:
perror ("sched_getscheduler");
break;
default:
fprintf (stderr, "Unknown policy!\n");
}
Linux implements a range of 1 to 99 inclusive for the two real-time scheduling policies
Linux provides two system calls for retrieving the range of valid priority values:
int min, max;
min = sched_get_priority_min (SCHED_RR);
if (min == −1) {
perror ("sched_get_priority_min");
return 1;
}
max = sched_get_priority_max (SCHED_RR);
if (max == −1) {
perror ("sched_get_priority_max");
return 1;
}
printf ("SCHED_RR priority range is %d - %d\n", min, max);
實時調度的注意事項:
設計實時程序必須格外當心,can easily bring down the entire system
(1) 若是系統中沒有更高優先級的實時進程,CPU密集型 循環程序將會 一直運行到結束
(2) Take care not to starve the rest of the system of processor time
(3) If a real-time process busy-waits for a resource held by a lower-priority process, the real-time process will busy-wait forever.
(由於
低優先級進程不會運行從而釋放資源)