(乾坤未定,你我皆是黑馬!)
期末用了大概一週的時間完成了操作系統的課程設計,本來是隨便選的一個題目,(因爲上課的時候隱隱約約有點印象)然後仔細研究一下發現裏面的算法還是挺簡單的!然後額外加了一些附加的功能。算法實現基本先要了解四種算法的調度方式然後重新排序生成訪問磁道的順序(主要用冒泡排序)即可。
首先了解一下這幾種算法
1、先來先服務算法(FCFS)First Come First Service
這是一種比較簡單的磁盤調度算法。它根據進程請求訪問磁盤的先後次序進行調度。此算法的優點是公平、簡單,且每個進程的請求都能依次得到處理,不會出現某一進程的請求長期得不到滿足的情況。此算法由於未對尋道進行優化,在對磁盤的訪問請求比較多的情況下,此算法將降低設備服務的吞吐量,致使平均尋道時間可能較長,但各進程得到服務的響應時間的變化幅度較小。
2、最短尋道時間優先算法(SSTF) Shortest Seek Time First
該算法選擇這樣的進程,其要求訪問的磁道與當前磁頭所在的磁道距離最近,以使每次的尋道時間最短,該算法可以得到比較好的吞吐量,但卻不能保證平均尋道時間最短。其缺點是對用戶的服務請求的響應機會不是均等的,因而導致響應時間的變化幅度很大。在服務請求很多的情況下,對內外邊緣磁道的請求將會無限期的被延遲,有些請求的響應時間將不可預期。
3、掃描算法(SCAN)
掃描算法不僅考慮到欲訪問的磁道與當前磁道的距離,更優先考慮的是磁頭的當前移動方向。例如,當磁頭正在自裏向外移動時,掃描算法所選擇的下一個訪問對象應是其欲訪問的磁道既在當前磁道之外,又是距離最近的。這樣自裏向外地訪問,直到再無更外的磁道需要訪問纔將磁臂換向,自外向裏移動。這時,同樣也是每次選擇這樣的進程來調度,即其要訪問的磁道,在當前磁道之內,從而避免了飢餓現象的出現。由於這種算法中磁頭移動的規律頗似電梯的運行,故又稱爲電梯調度算法。此算法基本上克服了最短尋道時間優先算法的服務集中於中間磁道和響應時間變化比較大的缺點,而具有最短尋道時間優先算法的優點即吞吐量較大,平均響應時間較小,但由於是擺動式的掃描方法,兩側磁道被訪問的頻率仍低於中間磁道。
4、循環掃描算法(CSCAN)
循環掃描算法是對掃描算法的改進。如果對磁道的訪問請求是均勻分佈的,當磁頭到達磁盤的一端,並反向運動時落在磁頭之後的訪問請求相對較少。這是由於這些磁道剛被處理,而磁盤另一端的請求密度相當高,且這些訪問請求等待的時間較長,爲了解決這種情況,循環掃描算法規定磁頭單向移動。例如,只自裏向外移動,當磁頭移到最外的被訪問磁道時,磁頭立即返回到最裏的欲訪磁道,即將最小磁道號緊接着最大磁道號構成循環,進行掃描。
先介紹一下這四種算法我的實現思路:(首先設置開始磁道位置)
先來先服務:按照輸入的磁道順序直接訪問,記錄下每一個磁道的尋道的地址。
最短尋道:對訪問順序進行排序,先找到距離開始磁道最近的磁道,然後把用該磁道的位置替換成開始磁道,之後遍歷尋找剩餘位置中距離開始磁道最近的位置(開始磁道已經被上一次替換),重新生成訪問順序。
掃描算法:也叫電梯算法,首先把要訪問的數組,分成兩個數組,一個全部比開始位置小的,一個全部比開始位置大的,然後新建一個數組利用這兩個數組重新在新數組裏面排序。根據掃描方式,很好理解的。
循環掃描算法:這個算法和掃描算法很類似,只是排序方式不同,從內向外排序之後,把另一串數組按照從小到大接在新數組後面,組件的方法大概和掃描算法類似。
1.功能界面:
2.創建磁道
3.先來先服務算法
4.最短尋道算法
5.掃描算法
6.循環掃描
7.算法優劣比較
8.退出
詳細代碼在這裏~可以留着參考 (點個關注再走唄!)
/**
磁盤調度算法3.0
製作人:圖南
**/
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
#include<windows.h>
#include <math.h>
#define MAX 200
//顯示菜單
void MEMU();
void color(int x);
void gotoxy(int a, int b);
void first();
void head();
void creat();
void FCFS();
void SSTF();
void SCAN();
void CSAN();
void compare();
//登陸界面
void first() {
color(2);
gotoxy(35, 8);
printf("磁盤調度3.0");
color(3);
gotoxy(38, 14);
printf("製作人:圖南 ");
}
//自定義函根據參數改變顏色
void color(int x)
{
//參數在0-15的範圍顏色
if (x >= 0 && x <= 15)
//只有一個參數,改變字體顏色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);
else
//默認的顏色白色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
/************調用函數設置光標位置 ***************/
void gotoxy(int a, int b) {
int xx = 0x0b;
HANDLE hOutput;
COORD loc;
loc.X = a;
loc.Y = b;
//獲取標準輸出的句柄
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//設置光標位置
SetConsoleCursorPosition(hOutput, loc);
return;
}
//標題顯示
void head()
{
color(10);
// gotoxy(20,20);
printf("\t\t\t----------------------------------------\n");
printf("\t\t\t| 磁 盤 調 度 |\n");
printf("\t\t\t----------------------------------------\n");
}
void MENU(){
head();
printf("\n");
color(12);
printf("\t本系統操作功能如下:\n");
printf("\t\t\t -----------------------------------------\n");
printf("\t\t\t| 1.創建磁道 (CREATE)... |\n");
printf("\t\t\t -----------------------------------------\n");
printf("\t\t\t| 2.先來先服務 (FCFS)... |\n");
printf("\t\t\t -----------------------------------------\n");
printf("\t\t\t| 3.最短尋道 (SSTF)... |\n");
printf("\t\t\t -----------------------------------------\n");
printf("\t\t\t| 4.掃描算法 (SCAN)... |\n");
printf("\t\t\t -----------------------------------------\n");
printf("\t\t\t| 5.循環掃描算法(CSCAN)... |\n");
printf("\t\t\t -----------------------------------------\n");
printf("\t\t\t| 6.算法優劣比較(COMPARE)... |\n");
printf("\t\t\t -----------------------------------------\n");
printf("\t\t\t| 7.退出 (EXIT)... |\n");
printf("\t\t\t -----------------------------------------\n");
printf("\t請選擇你要進行的操作::\n");
}
void main(){
first();
gotoxy(25, 25);
printf("請點擊任意鍵繼續使用。。。");
getch();
system("cls");
int cr=0;
while(1){
MENU();
int choice;
scanf("%d",&choice);
if(cr==0)
{
if(choice==1){
printf("現在開始創建!!!\n");
}else{
printf("必須先創建磁道喲!!!\n");
choice=1;
gotoxy(25, 35);
printf("請點擊任意鍵繼續使用。。。\n");
getch();
}
}
switch(choice)
{
case 1:
system("cls");
creat();
cr=1;
break;
case 2:
system("cls");
FCFS();
printf("請點擊任意鍵繼續使用。。。");
getch();
system("cls");
break;
case 3:
system("cls");
SSTF();
printf("請點擊任意鍵繼續使用。。。");
getch();
system("cls");
break;
case 4:
system("cls");
SCAN();
printf("請點擊任意鍵繼續使用。。。");
getch();
system("cls");
break;
case 5:
system("cls");
CSAN();
printf("請點擊任意鍵繼續使用。。。");
getch();
system("cls");
break;
case 6:
system("cls");
compare();
printf("請點擊任意鍵繼續使用。。。");
getch();
system("cls");
break;
case 7:
printf("再見!Bye~\n");
color(13);
gotoxy(25, 25);
printf("歡迎下次使用,再見!!!!!!");
exit(1);
default:
printf("Input error!(輸入數字有誤,請重新輸入))\n");
printf("請點擊任意鍵繼續使用。。。");
getch();
system("cls");
}
getchar();
}
MENU();
}
int num,sum,kai,max;
int m=0;
int n=0;
int s[100]; //記錄磁盤訪問順序
int s1[100]; //記錄磁盤移動距離
int c1[50]; //小於開始磁道遞減
int c2[50]; //大於開始磁道遞增
int visit[MAX]; //標記數組
double arr[4],arr2[4];
double avg1,avg2,avg3,avg4;
//創建磁道
void creat()
{
color(10);
printf("----------------------------------------------------\n");
printf("請輸入從哪個磁道開始:\t\n");
printf("----------------------------------------------------\n");
scanf("%d",&kai);
printf("----------------------------------------------------\n");
printf("請輸入最長磁道號:\n");
printf("------------------------------------------------------\n");
scanf("%d",&max);
printf("------------------------------------------------------\n");
printf("請輸入磁道的個數:\n");
printf("------------------------------------------------------\n");
scanf("%d",&num);
for(int j=0;j<num;j++)
{
printf("請輸入第%d個磁道\n",j+1);
scanf("%d",&s[j]);
if(s[j]>max)
{
printf("不可以,你輸入的磁道不能超過%d\n",max);
for(int j=0;j<num;j++){
s[j]=0;
}
break;
}
}
color(14);
printf("被訪問的下一個磁道\n");
for(int i=0;i<num;i++)
{
printf("%d:\t%d\t\n",i+1,s[i]);
}
int su=kai;
int t;
//比開始磁道小的放入c1 比開始磁道大的放入c2
for(int i=0;i<num;i++)
if(su>s[i])
c1[m++]=s[i];
else
c2[n++]=s[i];
//按照從大到小的順序排列
for(int i=0;i<m;i++)
for(int j=i;j<m;j++)
if(c1[i]<c1[j])
{
t=c1[i];
c1[i]=c1[j];
c1[j]=t;
}
//c2數組按照磁道從小到大的順序排列
for(int i=0;i<n;i++)
for(int j=i;j<n;j++)
if(c2[i]>c2[j])
{
t=c2[i];
c2[i]=c2[j];
c2[j]=t;}
}
//先來先服務算法(FCFS)
void FCFS()
{
printf("先來先服務 FCFS(從%d號磁道開始)\n",kai);
printf("----------------------------------------------------\n");
printf("被訪問的下一個磁道\t\t\t磁道號移動距離\n");
int su=kai;
sum=0;
for(int i=0;i<num;i++)
{ if(su<s[i])
s1[i]=s[i]-su;
else
s1[i]=su-s[i];
su=s[i];
sum+=s1[i];
}
for(int i=0;i<num;i++)
{
printf("\t%d\t\t\t\t\t%d\t\t\n",s[i],s1[i]);
}
printf("尋道長度:%d\n",sum);
avg1=(double)sum/num;
printf("平均尋道長度:%.2lf\n",avg1);
// printf("%f\n",avg1);
arr[0]=avg1;
}
//最短尋道時間優先算法(SSTF)
void SSTF()
{
printf("最短尋道 SSTF(從%d號磁道開始)\n",kai);
printf("----------------------------------------------------\n");
printf("被訪問的下一個磁道\t\t\t磁道號移動距離\n");
int k;//記錄最近的磁道號
int su;
int shortest; //記錄最短的距離
int s2[100];
memset(visit,1,sizeof(visit));//數組初始化爲1
su=kai;
sum=0;
for(int i=0;i<num;i++){
shortest=MAX;
for(int j=0;j<num;j++){ //比較得出最近的磁道
if(visit[j]){
if(fabs(su-s[j])<shortest){
shortest=fabs(su-s[j]);
k=j;
}
}
}
s1[i]=shortest;//記錄移動的距離
su=s[k]; //跟蹤當前磁頭所在位置
visit[k]=0; //標記已訪問
s2[i]=s[k]; //記錄路徑
}
for(int i=0;i<num;i++){
sum=s1[i]+sum;
}
for(int i=0;i<num;i++)
{
printf("\t%d\t\t\t\t\t%d\t\t\n",s2[i],s1[i]);
}
printf("尋道長度:%d\n",sum);
avg2=(double)sum/num;
printf("平均尋道長度:%.2lf\n",avg2);
arr[1]=avg2;
}
//掃描算法(SCAN)電梯調度
void SCAN()
{
printf("掃描算法 SCAN(從%d號磁道開始)\n",kai);
printf("----------------------------------------------------\n");
printf("被訪問的下一個磁道:\t\t\t磁道號移動距離:\n");
int su=kai;
int s2[100];
sum=0;
//s2排序設置成增加方向訪問
for(int i=0;i<n;i++)
s2[i]=c2[i];
for(int i=0;i<m;i++)
s2[i+n]=c1[i];
for(int i=0;i<num;i++)
{ if(su<s2[i])
s1[i]=s2[i]-su;
else
s1[i]=su-s2[i];
su=s2[i];
sum+=s1[i];
}
for(int i=0;i<num;i++)
{
printf("\t%d\t\t\t\t\t%d\t\t\n",s2[i],s1[i]);
}
printf("尋道長度:%d\n",sum);
avg3=(double)sum/num;
printf("平均尋道長度:%.2lf\n",avg3);
arr[2]=avg3;
}
//循環掃描算法(CSCAN)
void CSAN()
{
printf("循環掃描 CSAN(從%d號磁道開始)\n",kai);
printf("----------------------------------------------------\n");
printf("被訪問的下一個磁道:\t\t\t磁道號移動距離:\n");
int su=kai;
int j=0;
int s2[100];
sum=0;
//把c2添加到s2中,c1按照相反的順序添加
for(int i=0;i<n;i++)
s2[i] =c2[i];
for(int i=m-1;i>=0;j++,i--)
s2[j+n]=c1[i];
for(int i=0;i<num;i++)
{ if(su<s2[i])
s1[i]=s2[i]-su;
else
s1[i]=su-s2[i];
su=s2[i];
sum+=s1[i];
}
for(int i=0;i<num;i++)
{printf("\t%d\t\t\t\t\t%d\t\t\n",s2[i],s1[i]);
}
printf("尋道長度:%d\n",sum);
avg4=(double)sum/num;
printf("平均尋道長度:%.2lf\n",avg4);
arr[3]=avg4;
}
//比較不同算法的優劣
void compare(){
color(5);
int n;
int j;
int i;
double buf;
n=4;
for (i=0; i<n; ++i)
{
arr2[i]=arr[i];
}
//冒泡排序比較
for (i=0; i<n-1; i++)
{
for (j=0; j<n-1-i; j++)
{
if (arr2[j] > arr2[j+1])
{
buf = arr2[j];
arr2[j] = arr2[j+1];
arr2[j+1] = buf;
}
}
}
// printf("磁盤調度算法\t 平均尋道長度\n");
printf("\t平均尋道長度排序爲:");
for (i=0; i<n; ++i)
{
printf("\t%.2lf\t", arr2[i]);
}
printf("\n");
printf("---------------------------------------------------------------\n");
char a[]="先來先服務算法";
char b[]="最短尋道算法";
char c[]="掃描算法";
char d[]="循環掃描算法";
printf("\t磁盤調度算法\t 平均尋道長度\n");
printf("\t%s\t %.2lf\n",a,avg1);
printf("\t%s\t %.2lf\n",b,avg2);
printf("\t%s\t %.2lf\n",c,avg3);
printf("\t%s\t %.2lf\n",d,avg4);
printf("\n");
}