Ready-Suspend( Swap-out ):支持此行為( trainsition )的理由: \(^{[1]}\) 所有 blocked process 皆 swap-out 後 memory 仍不足時。 \(^{[2]}\)所有 blocked state process 之優先權皆高於 ready state process 時。
Running-Suspend( Swap-out ):這是一個不好的設計,但仍可以支持主要是因為若有一個高優先權process 從 「Blocked/suspend」變為「Ready/suspend」時,則作業系統可以強迫低優先權的process放掉 CPU 及 memory,供高優先權的 process 使用。
int value = 5; // global varible intmain(void){ pid_t pid; pid = fork(); if (pid == 0) { // child process value += 15; return0; } elseif (pid > 0) { // parent process wait(NULL); printf("PARENT: value = %d\n",value); // LINE A value -> 5 return0; } return0; }
\(Ex6.\) 有幾個 process 被建立了? including main() (Ref p. 4-54, Text book p. 150)
1 2 3 4 5 6 7 8 9 10 11
#include<stdio.h> #include<unistd.h> intmain(){ /* fork a child process */ fork(); /* fork another child process */ fork(); /* and fork another */ fork(); return0; }
排班效能最差,即 Avg. waiting time & Avg. turnaround time 最長 (其他準則不看)。
可能有「Convoy effect - 護衛效應」,許多 processes 均等待一個需要很長 CPU time 之 process 完成工作,才能取得 CPU,導致 Avg. waiting time 太長。
非常公平。
沒有 starvation 現象。
Non-premptive,不可搶奪、插隊。
SJF ( Shortest Job First )
具有最小 CPU time 的 process,優先取得 CPU。
1527472805224
到達時間皆為 0。
Gantt chart。
1527472898945
Avg. waiting time
\[
\frac{(0-0+(3-0)+(9-0)+(16-0)}{4}=7
\]
分析
排班效益最佳( Optimal ) 即 Avg. waiting/turnaround time 最小。 Proof:
1527473571408
由上圖可知 Waiting time for long job:\(0 \rightarrow CPU \; execution \; time_{short \; job}\) Waiting time for short job:\(CPU \; execution \; time_{long \; job} \rightarrow 0\) Avg. waiting ime:\(\frac{(CPU \; execution \; time_{short \; job}-0)+(0-0)}{2} < \frac{(0-0)+(CPU \; execution \; time_{long \; job}-0)}{2}\)
以這種方式 Short job 所減少的等待時間必定大於等於 Long job 所增加的等待時間,所以會使平均等待時間變小,最後可歸納到必為最佳的排班法則。
不公平,偏好 short job。
可能會 Starvation (for long job)。
又可以分為:
Non-preemptive ( SJF )
Preemptive ( SRTF or SRJF )
較不適合用在 shortest-trem scheduler,因為 short-term schduler 執行頻率太高,所以很難在極短時間內預估出精確每個process 的 CPU burst time 又要挑出最小值,不易真正呈現出 SJF 之行為;但比較適合 long-term schduler。
SRTF ( Shorest Remaining-time Job First )
又稱為 SRJF 或 SRTN ( Shorest Remaining-time Job Next ),即為「Preemptive - SJF」,將剩餘 CPU burst time 最小的 Process 取得 CPU,若「新到達的 process」 的 CPU burst time 目前執行中 process 剩下的 CPU time ,則新到達的 Process 可以插隊( Preemption )目前執行中的 Process。
Consider a preemptive priority scheduling algorithm based on dynamically changing priorities
Larger priority numbers imply higher priority
When a process is waiting for the CPU (In the ready queue, but not running), its priority changes at a rate α
When it is running, its priority changes at a rate β
All processes are given a priority of 0 when they enter the ready queue
What is the algorithm that results from β > α > 0 ?
因為 β 的值比 α 還高,所以隨著該程序不斷在 CPU 執行,其優先權提升的變化度會比在「Ready queue」的程序還高,這使得「Ready queue」中的程序其優先權不可能大到可以插斷 CPU 正在執行的程序,所以為「FCFS排班演算法」
What is the algorithm that results from α < β < 0?
因為「Ready queue」的程序,其遞減變化度 α 會比在 CPU 執行的程序的遞減變化度 β 還高,新加入的優先權為零,而「Ready queue」的程序與正在 CPU 執行的程序優先權總是隨著時間遞減,所以新加入的程序永遠可以插斷目前執行的程序,且因為在 CPU 執行的程序遞減程度較緩,所已不可能被「Ready queue」中的程序插斷,所以為「LIFO排班演算法」
(補充) CPU utilization 計算
Modern 版
假設採 RR 排班,令 Time quantum 為 Q、Context switching time 為 S, Process 平均執行每隔 T 時間會發出 I/O-request,求下列狀況的 CPU utilization。
方法一: 每個CPU 共享同一個 Ready queue ,當一個 CPU 完程某 Process 後,就去存取 Ready queue。 設計重點:
必須提供上述 Ready queue 的互斥存取之機制,若未提供,則可能發生 Process 重複執行,或有 Process 被忽略的錯誤。 例:CPU 去取 Process 之工作如下: 第一步,取得(read) Queue Front 端 Process 之 PCB pointer;第二步,從 Queue 中刪除此 Process pointer 。
不須考慮附載平衡 (load balance),因為每個 CPU 在工作都做完時會再繼續從 Ready queue 中挑選工作,不會讓自己閒置(idle)。
方法二:每個 CPU 都有自己的 Ready queue ,每個 CPU 只會檢查自己的 Ready queue ,不會去檢查其他 CPU 的 Ready queue ,有工作就執行,無工作就閒置 (idle)。 設計重點:
不須有互斥存取的考量。
需考慮附載平衡 ( Load balanceing ),避免 CPU 之勞務不均 (有人忙、有人閒)。 通常使用 2 種機制來調整 CPU 的附載 ( loading ):
Push migration ( 移轉 ) --- 像是領班、工頭
Pull migration --- 好同事
Process affinity
在 multiprocesors system 中,當 Process 已決定某 CPU 上執行,則在他執行過程之中,盡量不要將之移轉到其他 CPUs 上執行,除非有其必要。( 如:Processor bad、Load balancing... )避免 CPU 之 Cache、暫存器的內容要複製且又要刪除該工作,而影響效能。
有兩種 Affinity:
Hard-affinity:該 Process 不可移轉。
Soft-affinity:盡可能不移轉。( 若有需要,仍可移轉。)
Real-time system 排班設計考量
Hard read-time system
1528098291707
排班設計考量
確認這些工作是否可排程 ( schedulable )?也就是 CPU 可否負荷? 判斷公式:若 \(\sum_{i = 1}^n \frac{C_i}{P_i} \leq 1\)則為可排程,反之為不可排程。 其中:\(n\) 表示 Real-time event (Process)之數目、 $C_i$1表示 \(Event_i\) (Process)之所需 CPU time、P_i 表示 \(Event_i\) (Process)之發生週期( Period time )。 例:有下列四個 Real-time event ,其 CPU burst time 分別是:20 ms、50 ms、30 ms、X ms。其 period time 分別是 80ms、100ms、300ms、1ms。則在可排程的要求情況下,X 不可超過多少? Ans:\(\frac{20}{80}+\frac{50}{100}+\frac{30}{300}+\frac{X}{1000} \leq 1 \Rightarrow \frac{X}{1000} \leq 0.15 \Rightarrow X \leq 150\) (ms)。
再考慮是否可以滿足各工作的 Dead line。有兩個排班則:
Rate-monotonic scheduling
EDF ( Eaeliest Deadline First )
如何排程,以滿足各工作的 deadline?
Rate-monotonic
採取靜態的優先權值且可插隊( Preemptive )。
Period time 愈小,優先權值愈高。
$Ex1. $
Process
Period time
CPU time
P1
50
20
P2
100
35
是否可排程化?
\(\frac{20}{50}+\frac{35}{100}=0.4+0.35=0.75 \leq 1 \Rightarrow\) OK
盡可能降低 kernel dispatch latency time,可得 read-time process 可以即早工作。
降低 lermel latency 的困難處:
大部分的作業桶接不允許 kernel 整在執行 system call 或其他 system processes 時被 user process 任意的插隊 (preemption),目的是要確保 kernel data structures 的正確性(就是避免有 race condition),但是這種做法對於 soft real-time system 極為不利。
假設目前 kernel 正在執行一個「long-time」system call ( I/O-operation ) 而此時有一個 soft real-time process 到達(或是 fork()),但是他必須到 kernel 完成此 long-time system call 後才能取得 CPU。(Dispatch latency 太長)。要解決此問題原則是:必須插隊 kernal 且要保障 kernel data structure之正確性。
方法一 - Preemptive point
在 system call code 中加入一些「preemptive point」( 在此時點將 kernel 插隊是安全的 ),將來system call 執行時若遇到 preemptive point,system call 會先暫停 kernel 會檢查此時是否有 real-time process 到達。若有,方才的 kernel system call 會暫停執行, CPU 分派給 real-time process 使用;若無,方才的 kernel system call 繼續執行直到遇見下一個 preemptive point。
Cons:system call 中可以加入的 preemption point 數目不夠多(插入點有限),Dispatch latency 仍然很長。
方法二 - kernel 可隨時被 real-time process 插隊
需要具備有對於 kernel 的共享 data structure/resource 提供嚴謹的「互斥存取」( synchronization機制 ),以確保資料之正確性。
Cons:使用互斥存取可能造成「優先權反轉 ( Priority inversion )」問題。
Priority inversion - 優先權反轉
高優先權的 process 所需要的共享 data/resourses 恰巧被一些低優先全 process 所把持,無法存取 (因為互斥存取控制),造成高優先權等待低優先權 process 之情況,再加上低優先權 process 往往無法很快的取得 CPU ,已完成對共享 data/resources 之使用進而釋放資源,所以高優先權 process 被迫要等一段很久的時間。
解決方法:讓低優先權 process 暫時繼承高優先權的權值,使得低優先權 process 可以很快的 取得 CPU 完成共享 data/resource 之使用並釋放資源,同時也立刻恢復其原本的低權值。
Real-time system 之 dipatch latency 的架構
由兩個 phases 組成:
Conflict phase
Preempts kernel
低優先權釋放高優先權之 data/resource
Disoatch phase
Context switching
Change mode to user mode
Jump
1528637800281
Thread management
Thread:又稱之為「Lightweight proces」,為作業系統分配 CPU time 之基本單位 (It's a basic unit of CPU utilization)。( Process 是分配資源如:I/O, memory,的最基本單位 )
Other OS resources (Open files, I/O resources, siginal, ...)
Code section 與 Data section 合稱為 Memory address space。
Tradition process (Single-thread model)
1528638942439
Multithreading mode
1528639073333
Pros
Responsiveness:當 process 內執行中的 thread 被 blocked,則 CPU 可以交給此 process 內其他可執行的 threads 執行,故整個 process 不會被 blocked,仍持續執行,所以若將 multithreading 用在 user-interactive application,可增加對使用者之回應程度。
Resource sharing:因為 process 內之多條 threads 共享此 process code section,所以在同一個 memory space 上可有多個工作同時執行。
Economy:因為同一個 process 內之不同 threads 彼此共享此 process 的 memory 及其他作業系統的資源,所以 thread 之私有成份量少,故 thread 之 creation、context switching 更快、Thread 的管理成本更少。
Scalability (Utilization of multiprocessors Architecture):可以做到同一個 Process 內之不同 threads 可在不同 CPUs 上平行執行,所以可以增加對 multiprocessors system 之效益(平行程度)提升。
Thread management 是由在 User mode 之 thread library 提供的 APIs 以讓 user process 呼叫使用、管理。Kernel 完全不知道( be unknowed with ) user level threads 的存在。(只知道有 process 的 single thread)所以 thread management 不須 kernel 介入干預。
Pros
Thread creation、context switching ...等管理成本低,速度快。
Cons
當 Process 內某條執行中的 user-thread 是被 blocked 的,會導致整個 porcess 亦被 blocked。( 即使 process 內還是有其他可執行的 thread。)
因為無法做到 process 內之多條 user-threads 的平行執行,導致 Multprocessors 的效能發揮較差。
int sum; /* this data is shared by the thread(s) */ void *runner(void *param); /* threads call this function */
intmain(int argc, char *argv[]){ pthread_t tid; /* the thread identifier */ pthread_attr_t attr; /* set of thread attributes */ if (argc != 2) { fprintf(stderr,"usage: a.out <integer value>\n"); return-1; } if (atoi(argv[1]) < 0) { fprintf(stderr,"%d must be >= 0\n",atoi(argv[1])); return-1; } /* get the default attributes */ pthread_attr_init(&attr); /* create the thread. 根據 attr 屬性值建立一條 thread,ID 記錄在 tid 中,執行 runner() 副程式*/ pthread_create(&tid, &attr, runner, argv[1]); /* wait for the thread to exit */ pthread_join(tid, NULL); printf("sum = %d\n",sum); // 輸出應為 15 }
/* The thread will begin control in this function */ void *runner(void *param){ //若為 static 變數就為全域共享變數。 int i, upper = atoi(param); sum = 0; for (i = 1; i <= upper; i++) sum += i; /*Thread 終止*/ pthread_exit(0); }