模拟电梯调度算法,实现对磁盘的驱动调度。

合集下载

磁盘调度算法的模拟实现及对比

磁盘调度算法的模拟实现及对比

磁盘调度算法的模拟实现及对比磁盘调度算法是操作系统中的一个重要组成部分,用于优化磁盘读写操作的效率,提高系统的响应速度和运行效率。

常见的磁盘调度算法包括先来先服务(FCFS)算法、最短寻道时间优先(SSTF)算法、电梯(Elevator)算法等。

在进行磁盘调度算法的比较和模拟之前,我们首先需要了解磁盘读写操作的基本原理。

磁盘是由许多磁道和扇区组成的,当操作系统需要对磁盘进行读写操作时,读写头需要按照特定的路径移动到目标扇区,这个过程称为寻道。

而磁头在寻道的过程中所花费的时间称为寻道时间。

不同的磁盘调度算法的主要目标就是使得寻道时间尽可能地短,从而提高磁盘的读写操作效率。

首先,我们来实现一个先来先服务(FCFS)算法的模拟。

FCFS算法是最简单的磁盘调度算法,它按照磁盘请求的先后顺序进行处理。

具体实现如下:```pythondef fcfs(disk_queue, start):head_movement = 0curr_pos = startfor request in disk_queue:head_movement += abs(request - curr_pos)curr_pos = requestreturn head_movement```上述代码中,`disk_queue`表示磁盘请求队列,`start`表示起始磁道号。

算法首先将磁头移动到起始磁道号`start`,然后按照磁盘请求的先后顺序对队列中的请求进行处理,计算磁头的移动距离。

最后返回磁头的总移动距离。

接下来,我们实现一个最短寻道时间优先(SSTF)算法的模拟。

SSTF 算法会选择离当前磁道最近的请求进行处理,从而减少磁头的寻道时间。

具体实现如下:```pythondef sstf(disk_queue, start):head_movement = 0curr_pos = startwhile disk_queue:min_distance = float('inf')min_index = -1for i, request in enumerate(disk_queue):distance = abs(request - curr_pos)if distance < min_distance:min_distance = distancemin_index = ihead_movement += min_distancecurr_pos = disk_queue.pop(min_index)return head_movement```上述代码中,算法首先将磁头移动到起始磁道号`start`,然后不断选择离当前磁道最近的请求处理,直到所有请求处理完毕。

磁盘调度操作系统实验报告

磁盘调度操作系统实验报告

磁盘调度操作系统实验报告一、实验目的:本次实验主要目的是通过模拟实现磁盘调度算法,加深对操作系统磁盘调度原理的理解,并学会使用操作系统磁盘调度算法解决实际问题。

二、实验内容:1.磁盘调度算法原理分析:磁盘调度算法是操作系统中的重要组成部分,它的任务是合理安排磁盘上数据的存取顺序,以提高磁盘的效率。

常见的磁盘调度算法有先来先服务(FCFS)、最短寻道时间优先(SSTF)、电梯算法(SCAN)等。

2.模拟实现磁盘调度算法:本实验选择最短寻道时间优先算法(SSTF)作为示例进行模拟实现。

SSTF算法的原理是优先选择离当前磁头位置最近的磁道进行访问,以减少磁头移动时间。

实验步骤:1.根据实际情况,创建一个磁道队列,记录需要访问的磁道序号。

2.初始化磁盘的起始位置和访问队列。

3.对访问队列进行排序,按照磁头当前位置到磁道的距离从小到大排列。

4.根据排序后的队列顺序,依次访问磁道,并记录磁头移动的距离。

5.计算平均寻道长度。

三、实验结果分析:通过模拟实现SSTF磁盘调度算法,我们获得了磁头对每个磁道的访问顺序和总共的磁头移动距离。

根据实验结果,我们可以发现SSTF算法相对于其他算法具有一定的优势。

在实际应用中,根据不同的实际情况,可以选择合适的磁盘调度算法以优化磁盘的访问效率。

四、实验总结:通过本次实验,我们对磁盘调度算法的原理和实现有了更深入的了解。

磁盘调度算法作为操作系统中一个重要的模块,对提高磁盘的读写效率起着重要的作用。

在实际应用中,我们需要根据具体问题选择合适的磁盘调度算法,以达到最优的访问效果。

磁盘驱动调度算法的模拟

磁盘驱动调度算法的模拟

实验四磁盘驱动调度算法的模拟一.实验内容:熟悉磁盘的结构以及磁盘的驱动调度算法的模拟,编程实现简单常用的磁盘驱动调度算法先来先服务(FIFO)、电梯调度算法、最短寻找时间优先算法、扫描(双向扫描)算法、单向扫描(循环扫描)算法等。

编程只需实现两个算法。

题目可以选取教材或习题中的相关编程实例。

编程语言建议采用c/c++或Java。

模拟程序鼓励采用随机数技术、动态空间分配技术,有条件的最好能用图形界面展现甚至用动画模拟。

实验性质:验证型。

二.实验目的和要求1)掌握使用一门语言进行磁盘驱动调度算法的模拟;2)编写程序将磁盘驱动调度算法的过程和结果能以较简明直观的方式展现出来。

三.实验原理、方法和步骤1. 实验原理磁盘驱动调度对磁盘的效率有重要影响。

磁盘驱动调度算法的好坏直接影响辅助存储器的效率,从而影响计算机系统的整体效率。

常用的磁盘驱动调度算法有:最简单的磁盘驱动调度算法是先入先出(F IFO)法。

这种算法的实质是,总是严格按时间顺序对磁盘请求予以处理。

算法实现简单、易于理解并且相对公平,不会发生进程饿死现象。

但该算法可能会移动的柱面数较多并且会经常更换移动方向,效率有待提高。

最短寻找时间优先算法:总是优先处理最靠近的请求。

该算法移动的柱面距离较小,但可能会经常改变移动方向,并且可能会发生进程饥饿现象。

电梯调度:总是将一个方向上的请求全部处理完后,才改变方向继续处理其他请求。

扫描(双向扫描):总是从最外向最里进行扫描,然后在从最里向最外扫描。

该算法与电梯调度算法的区别是电梯调度在没有最外或最里的请求时不会移动到最外或最里柱面,二扫描算法总是移到最外、最里柱面。

两端的请求有优先服被务的迹象。

循环扫描(单向扫描):从最外向最里进行柱面请求处理,到最里柱面后,直接跳到最外柱面然后继续向里进行处理。

该算法与扫描算法的区别是,回来过程不处理请求,基于这样的事实,因为里端刚被处理。

2. 实验方法1)使用流程图描述演示程序的设计思想;2)选取c/c++、Java等计算机语言,编程调试,最终给出运行正确的程序。

操作系统课程设计-模拟电梯调度算法 实现对磁盘的驱动调度

操作系统课程设计-模拟电梯调度算法 实现对磁盘的驱动调度

衡阳师范学院操作系统课程设计报告设计题目:驱动调度系别:计算机科学系专业:计算机科学与技术(师范)班级:1001班姓名:XXX学号:XXX指导教师:XXX2012年11月26日目录一、程序设计内容原理及目的·······························1、设计内容················································`2、设计原理·················································3、设计目的·················································二、程序设计过程·········································1、驱动调度中的数据结构设计·································2、程序算法设计··············································三、用户手册··············································1、运行坏境··················································2、执行文件··················································四、程序实现及运行结果····································1、源代码····················································2、代码······················································3、运行结果·················································五、心得总结···············································六、参考文献···············································二、程序设计内容原理及目的1、设计内容模拟电梯调度算法,实现对磁盘的驱动调度。

驱动调度算法

驱动调度算法

驱动调度算法一、实验目的磁盘是一种高速、大容量、旋转型、可直接存取的存储设备。

他作为计算机系统的辅助存储器,担负着输入输出任务,在多道程序设计系统中,往往同时会有这若干个要求访问磁盘的输入输出请求等待处理。

系统课采用一种策略,尽可能按最佳次序执行要求访问磁盘的诸多输入输出请求。

这就叫驱动调度,使用的算法叫驱动算法。

二,实验内容模拟电梯调度算法,实现对磁盘的驱动调度。

三,源程序#include<stdio.h>#include<stdlib.h>#include<iostream.h>#include<math.h>#define maxsize 1000int decide(char str[]) //判断输入数据是否有效{int i=0;while(str[i]!='\0'){if(str[i]<'0'||str[i]>'9'){return 0;break;}i++;}return i;}int trans(char str[],int a) //将字符串转换成数字{int i;int sum=0;for(i=0;i<a;i++){sum=sum+(int)((str[i]-'0')*pow(10,a-i-1));}return sum;}int *bubble(int cidao[],int m){int i,j;int temp;for(i=0;i<m;i++) //使用冒泡法按从小到大顺序排列for(j=i+1;j<m;j++){if(cidao[i]>cidao[j]){temp=cidao[i];cidao[i]=cidao[j];cidao[j]=temp;}}cout<<"排序后的磁盘序列为:";for( i=0;i<m;i++) //输出排序结果{cout<<cidao[i]<<" ";}cout<<endl;return cidao;}void FCFS(int cidao[],int m) //先来先服务调度算法{int now; //当前磁道号int sum=0; //总寻道长度int j,i;int a;char str[100];float ave; //平均寻道长度cout<<"磁盘请求序列为:";for( i=0;i<m;i++) //按先来先服务的策略输出磁盘请求序列{cout<<cidao[i]<<" ";}cout<<endl;cout<<"请输入当前的磁道号:";B: cin>>str; //对输入数据进行有效性判断a=decide(str);if(a==0){cout<<"输入数据的类型错误,请重新输入!"<<endl;goto B;}elsenow=trans(str,a); //输入当前磁道号sum+=abs(cidao[0]-now);cout<<"磁盘扫描序列为:";for( i=0;i<m;i++) //输出磁盘扫描序列{cout<<cidao[i]<<" ";}for(i=0,j=1;j<m;i++,j++) //求平均寻道长度{sum+=abs(cidao[j]-cidao[i]);ave=(float)(sum)/(float)(m);}cout<<endl;cout<<"平均寻道长度:"<<ave<<endl;}void SSTF(int cidao[],int m) //最短寻道时间优先调度算法{int k=1;int now,l,r;int i,j,sum=0;int a;char str[100];float ave;cidao=bubble(cidao,m); //调用冒泡排序算法排序cout<<"请输入当前的磁道号:";C: cin>>str; //对输入数据进行有效性判断a=decide(str);if(a==0){cout<<"输入数据的类型错误,请重新输入!"<<endl;goto C;}elsenow=trans(str,a); //输入当前磁道号if(cidao[m-1]<=now) //若当前磁道号大于请求序列中最大者,则直接由外向内依次给予各请求服务{cout<<"磁盘扫描序列为:";for(i=m-1;i>=0;i--)cout<<cidao[i]<<" ";sum=now-cidao[0];}if(cidao[0]>=now) //若当前磁道号小于请求序列中最小者,则直接由内向外依次给予各请求服务{cout<<"磁盘扫描序列为:";for(i=0;i<m;i++)cout<<cidao[i]<<" ";sum=cidao[m-1]-now;}if(now>cidao[0]&&now<cidao[m-1]) //若当前磁道号大于请求序列中最小者且小于最大者{cout<<"磁盘扫描序列为:";while(cidao[k]<now) //确定当前磁道在已排的序列中的位置,后面的算法都用到了,可以直接复制后少量修改,节省时间。

操作系统驱动调度

操作系统驱动调度

操作系统实习报告姓名学号日期实验室指导教师设备编号实习题目实习九驱动调度一、实习内容模拟电梯调度算法,实现对磁盘的驱动调度。

二、实习目的磁盘是一种高速、大容量、旋转型、可直接存取的存储设备。

它作为计算机系统的辅助存储器,担负着繁重的输入输出任务、在多道程序设计系统中,往往同时会有若干个要求访问磁盘的输入输出请求等待处理。

系统可采用一种策略,尽可能按最佳次序执行要求访问磁盘的诸输入输出请求。

这就叫驱动调度,使用的算法称为驱动调度算法。

驱动调度能降低为若干个输入输出请求服务所需的总时间,从而提高系统效率。

本实验要求学生模拟设计一个驱动调度程序,观察驱动调度程序的动态运行过程。

通过实验使学生理解和掌握驱动调度的职能。

三、实习过程1.数据结构设计#define M 20typedef struct PCB{charproc[M];//进程名int cylinder_num;//柱面号int track_num;//磁道号int phy_num;//物理记录号struct PCB *next;}PCB;2.算法设计(1) 主函数框图如图1.1)主函数要求用户选择大于0.5 <电梯调度>小于0.5 <接受请求>2)进入模拟程序调用函数对输入值进行判定。

3)输入值大于0.5 初始化数组。

调用lift( )函数。

调用电梯调度算法。

调用输出函数output。

4)输入值小于0.5 调用接受请求函数。

接受进程输入请求,写入链表。

调用输出函数output。

5)要求用户选择是否继续Y.继续N.退出(2) 电梯调度算法lift() 如图3.1) 查I/O请求表,若等待进程表中有进程,则继续。

否则返回。

2) 若有与当前运行的进程的柱面号相同的进程访问,则选择能使旋转距离最短的访问者,并登记当前位置。

否则继续判断当前移臂方向。

3) 若当前移臂方向向里,则判断是否有比当前柱面号大的访问请求;否则判断是否有比当前柱面号小的访问请求。

实验二 模拟实现磁盘调度算法

实验二  模拟实现磁盘调度算法

实验二模拟实现磁盘调度算法姓名:班级:软件工程二班学号:日期:2020年12月13日实验目的:a、观察、体会操作系统的磁盘调度方法,并通过一个简单的磁盘调度模拟程序的实现,加深对磁盘调度的理解。

b、提高实际动手编程能力,为日后从事软件开发工作打下坚实基础。

实验内容:a、模拟实现磁盘调度算法:FCFS,最短寻道优先,电梯算法(参照给定的算法实现最短寻道优先算法,电梯算法(磁头向外))。

b、磁道请求服务顺序由用户输入(可通过从指定的文本文件(TXT文件)中取出)。

基本思想、原理和算法描述:(1)电梯算法磁头初始向外:思想和原理:用户输入一个初始磁道号,规定向外和向内,向外即先逐渐减小,当向外遍历完后,就掉头向里,向里则是逐渐增大。

设置一个变量了定义进程是否已经执行,每执行完一个就给它赋值,下次就不遍历。

算法描述:首先调用重置访问标志、磁头当前位置、总移动磁道数的函数,然后进入循环,在循环刚开始时候,定义一个非常大的容器用来存储移动磁道数。

比较移动磁道数的大小,把小的那个磁道的下标给iNEXT,并把移动磁道数改为当前磁道的磁道移动数,用于下一次比较。

然后累加总移动磁道数,移动磁头当前位置为当前访问磁道号,并设置磁道是否已经访问标志为1:已访问。

(2)最短寻道优先调度算法:思想和原理:要求访问的磁道与当前磁头所在的磁道距离最近,即要求移动的磁道数最小的后一个磁道先执行。

主要是比较下一个磁道与当前磁道的差,取差最小的那个磁道,后面以此类推。

算法描述:源程序和电梯算法相似,本算法只比较移动磁道数的大小。

循环比较,直到所有的磁道都遍历完。

源程序:(1)电梯算法磁头初始向外:case 2://磁头初始向外Reset();//重置访问标志、磁头当前位置、总移动磁道数cout<<endl<<"---------------------------------------------"<<endl;cout<<"电梯调度算法——磁头初始向外的调度结果: "<<endl<<endl;cout<<"初始磁道号: "<<iStart<<endl;cout<<"序号下一磁道号移动的磁道数"<<endl;for(i=0;i<iReqNum;i++){iMinMove=9999;iNext=-1;for(j=0;j<iReqNum;j++)//寻找当前方向上寻道距离最短的未访问磁道号在数组队列queue中的下标{if((queue[j].iBeVisited==0)&&(queue[j].iGo<=iNow)){if(abs(queue[j].iGo-iNow)<iMinMove){iNext=j;iMinMove=abs(queue[j].iGo-iNow);} //if(abs(queue[j].iGo-iNow)<iMinMove)} //if((queue[j].iBeVisited==0)&&(queue[j].iGo>=iNow))} //for(j=0;j<iReqNum;j++)if(iNext!=-1){//输出信息摸拟访问请求的磁道cout<<" "<<i+1<<" "<<queue[iNext].iGo<<" "<<abs(queue[iNext].iGo-iNow)<<endl;iSum+=abs(queue[iNext].iGo-iNow);//累加总移动磁道数iNow=queue[iNext].iGo;//移动磁头当前位置为当前访问磁道号queue[iNext].iBeVisited=1;//设置磁道是否已经访问标志为1:已访问} //if(iNext!=-1)else//掉头向外{for(j=0;j<iReqNum;j++)//寻找当前方向上寻道距离最短的未访问磁道号在数组队列queue中的下标{if((queue[j].iBeVisited==0)&&(queue[j].iGo>iNow)){if(abs(queue[j].iGo-iNow)<iMinMove){iNext=j;iMinMove=abs(queue[j].iGo-iNow);}}} //for(j=0;j<iReqNum;j++)//输出信息摸拟访问请求的磁道cout<<".."<<i+1<<"……"<<queue[iNext].iGo<<"…"<<abs(queue[iNext].iGo-iNow)<<endl;iSum+=abs(queue[iNext].iGo-iNow);//累加总移动磁道数iNow=queue[iNext].iGo;//移动磁头当前位置为当前访问磁道号queue[iNext].iBeVisited=1;//设置磁道是否已经访问标志为1:已访问} //if(iNext!=-1)} //for(i=0;i<iReqNum;i++)cout<<endl<<"总调度次数: "<<iReqNum<<endl;cout<<endl<<"总移动磁道数: "<<iSum<<endl;printf("\n平均移动磁道数: %.2f\n\n",(float)iSum / (float)iReqNum);break;default:printf("\n输入错误!!\n\n");return;}//switch(iInput)}运行结果:(2)最短寻道优先调度算法:void SSTF() //最短寻道优先调度算法{Reset();//重置访问标志、磁头当前位置、总移动磁道数cout << endl << "---------------------------------------------" << endl;cout << "最短寻道优先调度算法的调度结果: " << endl << endl;cout << "初始磁道号: " << iStart << endl;cout << "序号下一磁道号移动的磁道数" << endl;int numberend = 0;//已经运行的磁道的数目int size = 0;//当前磁道与某磁道的距离int NewiNow = 0;//记录与当前磁头距离最短的磁道的下标,初始化为0while (numberend != iReqNum)//已经运行的磁道的数目超出最大数目时退出循环{for (int i = 0; i < iReqNum; i++){if (!queue[i].iBeVisited){size = abs(iNow - queue[i].iGo);//初始化当前距离NewiNow = i;//跟新下标break;}}for (int i = 0; i < iReqNum; i++)//循环遍历,在为输出的磁道中寻找与当前磁道最近的磁道{if (!queue[i].iBeVisited&&size > abs(iNow - queue[i].iGo))//如果该磁道没有被访问,且距离小于当前距离{size = abs(iNow - queue[i].iGo);//更新磁道距离NewiNow = i;//跟新下标}}queue[NewiNow].iBeVisited = 1;//标记该磁道已访问iNow = queue[NewiNow].iGo;//移动磁头当前位置为当前访问磁道号iSum += size;//累加总移动磁道数++numberend;//更新已经访问磁道数目//输出信息摸拟访问请求的磁道cout << " " << numberend << " " << iNow << " " << size << endl;}cout << endl << "总调度次数: " << iReqNum << endl;cout << endl << "总移动磁道数: " << iSum << endl;printf("\n平均移动磁道数: %.2f\n\n", (float)iSum / (float)iReqNum);}运行结果分析:(2)最短寻道优先调度算法:实验总结:深刻理解FCFS,最短寻道优先,电梯算法。

驱动调度算法

驱动调度算法

一.模拟电梯调度算法,实现对磁盘的驱动调度二.程序中使用的数据结构及其说明typedefstruct Process//描述进程信息{char name[N]。

//进程名int cyl_num。

//请求的柱面号int tra_num。

//请求的磁道号int rec_num。

//请求的物理记录号int signal。

//标记位}process。

三.源程序及注释pro_struct.h#ifndef PRO_STRUCT_H#define PRO_STRUCT_H#define N 10typedefstruct Process//描述进程信息{char name[N]。

//进程名int cyl_num。

//请求的柱面号int tra_num。

//请求的磁道号int rec_num。

//请求的物理记录号int signal。

//标记位}process。

#endifpro_list.h#ifndef PRO_LIST_H#define PRO_LIST_H#include<iostream>#include<string.h>#include"pro_struct.h"usingnamespace std。

#define M 100void list(int pro_count,int pro_num,process pro[M]>//创建等待进程表b5E2RGbCAP{cout<<"等待的进程数:"。

cin>>pro_num。

if(pro_num>0&&(pro_num+pro_count><=M>//判断要输入的进程数是否合法,输入后是否超出进程等待表所允许的最大值p1EanqFDPw {cout<<"开始输入"<<endl。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

操作系统实验(第三次)一、实验内容模拟电梯调度算法,实现对磁盘的驱动调度。

二、实验目的磁盘是一种高速、大容量、旋转型、可直接存取的存储设备。

它作为计算机系统的辅助存储器,担负着繁重的输入输出任务、在多道程序设计系统中,往往同时会有若干个要求访问磁盘的输入输出请求等待处理。

系统可采用一种策略,尽可能按最佳次序执行要求访问磁盘的诸输入输出请求。

这就叫驱动调度,使用的算法称为驱动调度算法。

驱动调度能降低为若干个输入输出请求服务所需的总时间,从而提高系统效率。

本实验要求学生模拟设计一个驱动调度程序,观察驱动调度程序的动态运行过程。

通过实验使学生理解和掌握驱动调度的职能。

三、实验题目模拟电梯调度算法,对磁盘进行移臂和旋转调度。

[提示]:(1)磁盘是可供多个进程共享的存储设备,但一个磁盘每时刻只能为一个进程服务。

当有进程在访问某个磁盘时,其他想访问该磁盘的进程必须等待,直到磁盘一次工作结束。

当有多个进程提出输入输出要求而处于等待状态时,可用电梯调度算法从若干个等待访问者中选择一个进程,让它访问磁盘。

选择访问者的工作由“驱动调度”进程来完成。

由于磁盘与处理器是可以并行工作的、所以当磁盘在作为一个进程服务时,占有处理器的另一进程可以提出使用磁盘的要求,也就是说,系统能动态地接收新的输入输出请求。

为了模拟这种情况,在本实验中设置了一个“接收请求”进程。

“驱动调度”进程和“接收请求”进程能否占有处理器运行,取决于磁盘的结束中断信号和处理器调度策略。

在实验中可用随机数来模拟确定这两个进程的运行顺序,以代替中断四、处理和处理器调度选择的过程。

因而,程序的结构可参考图3—1(2)“接收请求”进程建立一张“请求I/O”表,指出访问磁盘的进程要求访问的物理地址,表的格式为:假定某个磁盘组共有200 个柱面,由外向里顺序编号(0—199),每个柱面上有20 个磁道,编号为0—19,每个磁道分成8 个物理记录,编号0—7。

进程访问磁盘的物理地址可以用键盘输入的方法模拟得到。

图3—2 是“接收请求”进程的模拟算法。

在实际的系统中必须把等待访问磁盘的进程排入等待列队,由于本实验模拟驱动调度,为简单起见,在实验中可免去队列管理部分,故设计程序时可不考虑“进程排入等待队列”的工作。

(3)“驱动调度”进程的功能是查“请求I/O”表,当有等待访问磁盘的进程时,按电梯调度算法从中选择一个等待访问者,按该进程指定的磁盘物理地址启动磁盘为其服务。

对移动臂磁盘来说,驱动调度分移臂调度和旋转调度。

电梯调度算法的调度策略是与移动臂的移动方向和移动臂的当前位子有关的,所以每次启动磁盘时都应登记移动臂方向和当前位子。

电梯调度算法是一种简单而实用的驱动调度方法,这种调度策略总是优先选择与当前柱面号相同的访问请求,从这些请求中再选择一个能使旋转距离最短的等待访问者。

如果没有与当前柱面号相同的访问请求,则根据移臂方向来选择,每次总是沿臂移动方向选择一个与当前柱面号最近的访问请求,若沿这个方向没有访问请求时,就改变臂的移动方向。

这种调度策略能使移动臂的移动频率极小,从而提高系统效率。

用电梯调度算法实现驱动调度的模拟算法如图3-3。

(4)图3-1 中的初始化工作包括,初始化“请求I/O”表,置当前移臂方向为里移;置当前位置为0 号柱面,0 号物理记录。

程序运行前可假定“请求I/O”表中已经有如干个进程等待访问磁盘。

在模拟实验中,当选中一个进程可以访问磁盘时,并不实际地启动磁盘,而用显示:“请求I/O”表;当前移臂方向;当前柱面号,物理记录号来代替图3-3 中的“启动磁盘”这项工作。

(1)程序中使用的数据结构及其说明。

const int PCB=100; //定义100个进程int pcbs_num=0; //记录当前io表的进程个数typedef struct process //请求io表{char pname[10]; //进程名int Cylinder; //柱面号int Track; //磁道号int Record; //物理记录号int Way;}PROCESS;PROCESS pcbs[PCB];PROCESS a; //记录当前位置(柱面号、物理记录号)采用带头节点的循环链表存(2)打印一份源程序并附上注释。

(3)#include<iostream>(4)#include<iomanip>(5)#include<stdio.h>(6)#include<cstdlib>(7)#include<fstream>(8)using namespace std;(9)const int PCB = 100; //定义100个进程(10)int pcbs_num = 0; //记录当前io表的进程个数(11)typedef struct process//请求io表(12){(13)char pname[10]; //进程名(14)int Cylinder; //柱面号(15)int Track; //磁道号(16)int Record; //物理记录号(17)int Way;(18)}PROCESS;(19)PROCESS pcbs[PCB];(20)PROCESS a;(21)void init_a() //设置当前位置(22){(23) a.Cylinder = 4;(24) a.Track = 0;(25) a.Record = 0;(26)}(27)int count_PN() //记录进程总数(28){(29)int i;(30)for (i = 0; pcbs[i].Cylinder != NULL; i++)(31){(32)}(33)cout << i << endl;(34)return i;(35)}(36)void accept() //接受请求模拟算法(37){(38)cout << "输入进程名和物理地址(柱面号,磁道号,物理记录号)" << endl;(39)cin >> pcbs[pcbs_num].pname >> pcbs[pcbs_num].Cylinder >>pcbs[pcbs_num].Track >> pcbs[pcbs_num].Record;(40)pcbs_num++;(41)}(42)int Cylinder_e() //判断柱面号相等(43){(44)for (int i = 0; i<pcbs_num; i++)(45){(46)if (pcbs[i].Cylinder == a.Cylinder)(47)return i;(48)}(49)return 0;(50)}(51)int Cylinder_near(int cylinder, int record) ////选择当前柱面号的访问者中物理块号最近的(52){(53)int t = 8, a, k;(54)for (int i = 0; i<pcbs_num; i++)(55){(56)if (pcbs[i].Cylinder == cylinder)(57){(58) a = pcbs[i].Record - record;(59)if (a<0){ a = a + 8; }(60)if (a<t)(61){(62)t = a; k = i;(63)}(64)}(65)}(66)return k;(67)}(68)int Cylinder_max(int cylinder) //选择比当前柱面号大的请求中柱面号最小的(69){(70)int num, t = 199, i, a = 0, b = 0;(71)for (i = 0; i < pcbs_num; i++)(72){(73)if((abs(pcbs[i].Cylinder - cylinder))<t && pcbs[i].Cylinder > cylinder) (74){(75)t = abs(pcbs[i].Cylinder - cylinder);(76)}(77)} num = cylinder + t; //选择的柱面号(78)t = 8; //物理块号最大相差7(79)for (i = 0; i<pcbs_num; i++)(80){(81)if (pcbs[i].Cylinder == num &&pcbs[i].Record < t)(82){(83)t = pcbs[i].Record; a = i;(84)}(85)}(86)return a;(87)}(88)int Cylinder_max1(int cylinder)(89){(90)int t = 199, i, b = 0, c = 0;(91)for (i = 0; i<pcbs_num; i++)(92){(93)if((abs(pcbs[i].Cylinder - cylinder))>b && pcbs[i].Cylinder > cylinder) (94){(95) b = abs(pcbs[i].Cylinder - cylinder);(96)}(97)}(98)return b;(99)}(100)int Cylinder_min(int cylinder) //选择比当前柱面号小的请求中柱面号最大的(101){(102)int num, t = 199, i, a = 0; for (i = 0; i < pcbs_num; i++)(103){(104)if((abs(pcbs[i].Cylinder - cylinder))<t && pcbs[i].Cylinder < cylinder) (105){(106)t = abs(pcbs[i].Cylinder - cylinder);(107)}(108)}(109)num = cylinder - t; t = 8; //物理块号相差最大为7(110)for (i = 0; i < pcbs_num; i++)(111){(112)if (pcbs[i].Cylinder == num && pcbs[i].Record <t)(113){(114)t = pcbs[i].Record; a = i;(115)}(116)}(117)return a; //返回柱面号小的请求中柱面号最大的下标(118)}(119)void delete_scan(int x)(120){(121)for (int i = x; i<pcbs_num; i++)(122)pcbs[i] = pcbs[i + 1]; pcbs_num--;(123)}(124)void print_io() //打印请求io表(125){(126)cout << "输出请求i/o表:" << endl;(127)cout << "进程名" << " 柱面号" << " 磁道号" << " 物理记录号" << endl;(128)for (int i = 0; i<pcbs_num; i++)(129){(130)cout << setfill(' ') << setw(6) << pcbs[i].pname << setfill(' ') << setw(8) << pcbs[i].Cylinder << setfill(' ') << setw(8) << pcbs[i].Track << setfill(' ') << setw(10) << pcbs[i].Record << endl;(131)}(132)}(133)void print_scan(bool x)(134){(135)cout << "选中的:"<< endl; cout << "进程名"<< " 柱面号"<< " 磁道号"<< " 物理记录号"<< " 方向"<< endl; cout << setfill(' ') << setw(6) << a.pname << setfill(' ') << setw(8) << a.Cylinder << setfill(' ') << setw(10) << a.Track << setfill(' ') << setw(10) << a.Record << setfill(' ') << setw(6) << x << endl;(136)}(137)int SCAN() //驱动调度电梯调度模拟算法(138){(139)print_io(); //打印io表(140)int scan;(141)int scan1;//scan为选择的进程的编号(142)bool way = 1; //方向 0=out 1=in(143)if (a.Cylinder == NULL)(144){(145)init_a();(146)}(147)if (pcbs_num == 0)(148){(149)cout << "无等待访问者" << endl; return 0;(150)}(151)else(152){(153)if (pcbs[Cylinder_e()].Cylinder == a.Cylinder) //选择能使旋转距离最短的访问者(154){(155)scan = Cylinder_near(a.Cylinder, a.Record);//选择当前柱面号的访问者中最近的(156)if (pcbs[scan].Cylinder<a.Cylinder)(157){(158)way = 0;(159)}(160)else way = 1;(161)}(162)else(163){(164)if (way == 1)(165){(166)scan = Cylinder_max(a.Cylinder); //选择比当前柱面号大的请求中物理块号最小的(167)scan1 = Cylinder_max1(a.Cylinder);(168)if (scan == scan1)(169){(170)scan = Cylinder_min(a.Cylinder); //选择比当前柱面号小的请求中物理块号最大的(171)way = 0;(172)}(173)}(174)else(175){(176)scan = Cylinder_min(a.Cylinder);(177)if (scan == 0)(178){(179)scan = Cylinder_max(a.Cylinder);(180)way = 1;(181)}(182)}(183)} a = pcbs[scan];(184)delete_scan(scan); //删除pcbs[scan](185)print_scan(way); //打印(186)return 1;(187)}(188)}(189)void work()//初始化(190){(191)float n; char y = 'y'; while (y == 'y' || y == 'Y')(192){(193)cout << "输入在[0,1]区间内的一个随机数" << endl;(194)cin >> n;(195)if (n>0.5)(196){(197)SCAN(); //驱动调度(198)}(199)else(200){(201)accept(); //接受请求(202)}(203)cout << "继续?(y/n)" << endl;(204)cin >> y;(205)}(206)}(207)void main()(208){(209)work();(210) }(4)打印驱动调度进程每次选择访问请求前的“请求I/O”表以及每次选中的进程名、访问的柱面号、物理记录号和当前移臂方向(用up 代表里移,down 代表外移。

相关文档
最新文档