1 處理機的調度層次和調度算法目標
2 批處理系統中的作業調度
2.1 先來先服務調度算法(first-come first-served,FCFS)
描述:FCFS是最簡單的調度算法,該算法可用於作業調度,也可用於進程調度,當在作業調度中採用該算法時,系統將按照作業到達的先後次序進行調度,或者說優先考慮在系統中等待時間最長的作業,而不管作業需要執行時間的長短,從後背作業隊列中選擇幾個最先進入該隊列的作業,將他們調入內存,爲他們分配資源和創建進程,最後放入就緒隊列。
當在進程中採用該算法時,每次調度從就緒的進程隊列中選擇一個最先進入該隊列的進程,爲之分配處理機,投入運行。該進程一直運行到完成或者發生某個時間阻塞時,進程調度將處理機分配給其他進程。
算法實現:
// Fsc.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//
#include "pch.h"
#include <iostream>
using namespace std;
int main()
{
int countHomework;
cout << "請輸入作業數量:" << endl;
cin >> countHomework;
double **arr = new double *[countHomework];
for (int i = 0;i < countHomework;i++)
{
arr[i] = new double[5];
}
for (int i = 0;i < countHomework;i++)//初始化
for (int j = 0;j < 5;j++)
arr[i][j] = 0;
double starttime, endtime;
cout << "請輸入開始時間和運行時間" << endl;
for (int i = 0;i < countHomework;i++) {
cin >> starttime >> endtime;
arr[i][1] = starttime;
arr[i][2] = endtime;
}
//排序
double temp_1;
double temp_2;
for (int i = 0;i < countHomework;i++)
{
for (int j = i + 1;j < countHomework;j++)
{
if (arr[i][1] > arr[j][1])
{
temp_1 = arr[i][1];
temp_2 = arr[i][2];
arr[i][1] = arr[j][1];
arr[i][2] = arr[j][2];
arr[j][1] = temp_1;
arr[j][2] = temp_2;
}
}
}
double currentTime;
currentTime = arr[0][1];
arr[0][3] = currentTime+arr[0][2];//作業完成時間
currentTime = arr[0][3];
arr[0][4] = currentTime-arr[0][1];//週轉時間
for (int i = 1;i < countHomework;i++)
{
arr[i][3] = currentTime + arr[i][2];//計算完成時間
currentTime += arr[i][2];
arr[i][4] = currentTime - arr[i][1];//計算週轉時間
}
cout << "進程號\t" << "開始時間\t" << "運行時間\t" <<"完成時間\t"<< "週轉時間\t" << endl;
for (int i = 0;i < countHomework;i++) {
arr[i][0] = i + 1;
for (int j = 0;j < 5;j++)
{
cout << arr[i][j] << "\t\t";
}
cout << endl;
}
}
2.2 短作業優先調度算法(short job first,SJF)
SJF算法是以作業的長短來計算優先級,作業越短優先級越高,作業長短是以作業運行時間長短來衡量。SJF算法可以分別用於作業調度和進程調度,再把短作業優先調度算法用於作業調度時,它將外存的作業後背隊列中選擇若干個估計運行時間最短的作業,優先將他們調入內存。
缺點:
(1)必須預知作業的運行時間,但一般很難預測每個作業運行時間的長短,如果預計過低,系統就可能按估計時間終止作業的運行,但此時作業未完成,所以一般偏長估計。
(2)對長作業不利,長作業週轉時間明顯變長,該算法完全忽視作業等待時間,可能使作業等待時間過長,出現飢餓現象。
(3)採用SJF算法時,人機無法交互。
(4)該算法沒有考慮作業的緊迫程度,所以不能保證緊迫的作業得到及時處理。
算法實現:
#include "pch.h"
#include <iostream>
using namespace std;
int main()
{
cout << "請輸入進程個數:" << endl;
int processNumber;
cin >> processNumber;
double **array = new double*[processNumber];
for (int i = 0;i < processNumber;i++)//申請空間
{
array[i] = new double[5];
}
for (int i = 0;i < processNumber;i++)//初始化
{
for (int j = 1;j < 5;j++)
array[i][j] = 0;
}
double startTime = 0.0, endTime = 0.0;
cout << "請輸入每個進程到達時間和執行時間:" << endl;
for (int i = 0;i < processNumber;i++) {//輸入每個進程開始和運行時間
cin >> startTime >> endTime;
array[i][1] = startTime;
array[i][2] = endTime;
}
double currentTime = array[0][1];//初始化當前時間,運行第一個進程
array[0][3] = currentTime + array[0][2];
currentTime += array[0][2];//當前時間,執行完第一個進程
array[0][4] = currentTime - array[0][1];
array[0][0] = 1;
double temp = 0;
//排序
for (int i = 1;i < processNumber;i++)
{
for (int j = i + 1;j < processNumber;j++)
{
if (array[i][2] > array[j][2])
{
temp = array[i][2];
array[i][2] = array[j][2];
array[j][2] = temp;
temp = array[i][1];
array[i][1] = array[j][1];
array[j][1] = temp;
}
}
}
int count = 1;
while (count < processNumber) {
for (int i = 1;i < processNumber;i++)
{
if( (array[i][1] <=currentTime)&&(array[i][0] != 1))
{
currentTime += array[i][2];
array[i][3] = currentTime;//填入進程完成時間
array[i][4] = currentTime - array[i][1];//週轉時間
count++;
array[i][0] = 1;
break;
}
}
}
for (int i = 0;i < processNumber;i++)
{
array[i][0] = i + 1;
}
cout << "進程號\t" << "開始時間\t" <<"運行時間\t"<<"完成時間\t"<<"週轉時間\t"<< endl;
for (int i = 0;i < processNumber;i++)
{
for (int j = 0;j < 5;j++)
cout << array[i][j] << " \t\t";
cout << endl;
}
}
2.3 優先級調度算法和高響應比優先調度算法(Heigest Response Ratio Next,HRRN)
我們可以這樣理解優先級,對於先來先服務算法,作業的等待時間就是其優先級,等待時間越長,優先級越高。對於短作業調度算法,作業所需運行時間越短優先級越高。
在批處理系統中,短作業優先算法是一種比較好的算法,其主要的不足之處是長作業 的運行得不到保證。如果我們能爲每個作業引入前面所述的動態優先權,並使作業的優先 級隨着等待時間的增加而以速率 a 提高,則長作業在等待一定的時間後,必然有機會分配 到處理機。該優先權的變化規律可描述爲:
優先權=(要求服務時間 等待時間)/ 要求服務時間 , 由於等待時間與服務時間之和就是系統對該作業的響應時間,故該優先權又相當於響 應比 RP。據此,又可表示爲:
RP=(要求服務時間 等待時間)/ 要求服務時間 = 響應時間 /要求服務時間 , 由上式可以看出:
(1) 如果作業的等待時間相同,則要求服務的時間愈短,其優先權愈高,因而該算法有 利於短作業。
(2) 當要求服務的時間相同時,作業的優先權決定於其等待時間,等待時間愈長,其優 先權愈高,因而它實現的是先來先服務。 (3) 對於長作業,作業的優先級可以隨等待時間的增加而提高,當其等待時間足夠長時, 其優先級便可升到很高,從而也可獲得處理機。 簡言之,該算法既照顧了短作業,又考慮了作業到達的先後次序,不會使長作業長期 得不到服務。因此,該算法實現了一種較好的折衷。當然,在利用該算法時,每要進行調 第三章 處理機調度與死鎖 ·95· 度之前,都須先做響應比的計算,這會增加系統開銷。
#include"pch.h"
#include<iostream>
using namespace std;
int main()
{
int jobNum = 0;
cout << "請輸入作業數量" << endl;
cin >> jobNum;
double **arr = new double*[jobNum];
for (int i = 0;i < jobNum;i++)
{
arr[i] = new double[5];
}
for (int i = 0;i < jobNum;i++)
for (int j = 0;j < 5;j++)
arr[i][j] = 0;
double startTime = 0, runningTime = 0;
cout << "請輸入開始時間和運行時間" << endl;
for (int i = 0;i < jobNum;i++)//輸入時間
{
cin >> startTime >> runningTime;
arr[i][1] = startTime;
arr[i][2] = runningTime;
arr[i][0] = 0;
}
//初始化
double currentTime = arr[0][1];//初始化當前時間
arr[0][3] = arr[0][1] + arr[0][2];//完成時間
currentTime = arr[0][3];
arr[0][4] = currentTime - arr[0][1];//週轉時間
cout << currentTime << endl; arr[0][0] = 1;//作爲標誌
int count = 1;
double priority = 0;//定義優先級
while (count < jobNum)
{
int i_job = 0;//作業記錄
double maxPriority = 0;//定義最大優先級
for (int i = 1;i < jobNum ;i++)//找出優先級最大的作業
{
if ((arr[i][0] != 1) && (arr[i][1] <=currentTime)) {
priority = (currentTime - arr[i][1] + arr[i][2]) / (arr[i][2]);//求出優先級
if (maxPriority < priority) {
maxPriority = priority;
i_job = i;
}
}
}
arr[i_job][3] = arr[i_job][2]+currentTime;//記錄作業完成時間
currentTime += arr[i_job][2];//運行作業保存當前時間
arr[i_job][4] = currentTime - arr[i_job][1];//記錄週轉時間
arr[i_job][0] = 1;
count++;
}
cout << "作業號\t" << "開始時間\t" << "運行時間\t" << "結束時間\t" << "週轉時間" << "\t" << endl;
for (int i = 0;i < jobNum;i++)
{
arr[i][0] = i + 1;
cout << arr[i][0] << "\t\t" << arr[i][1] << "\t\t" << arr[i][2] << "\t\t" << arr[i][3] << "\t\t" << arr[i][4] << "\t\t" << endl;
}
}