版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
PAGE41-广西工学院鹿山学院操作系统实训报告系别:计算机软件工程专业班级:082班姓名:高祥学号:20081432 指导教师:胡艳华二〇一〇年11月28日任务一
分析操作系统所面临的操作需求【实训目的】使学生理解操作系统所面临的操作需求,掌握操作系统中的进程管理、存储管理、设备管理和文件管理等功能。【实训内容】1.
分析操作系统所面临的操作需求;2.
熟悉实训环境;3.
资料搜集与整理,进行实训的前期准备。【实训步骤】分析与设计(详细分析设计,并给出流程图)
【思考题】1.
操作系统中各模块有怎样的功能?操作系统中的各个模块都有不同的功能:进程管理模块用于分配和控制处理机;设备管理模块主要负责对I/O设备的分配与操纵;文件管理主要负责文件的存取、共享和保护;存储管理主要负责的分配与回收。2.
它们之间有怎样的联系?它们之间相互联系,关系密切,无论是设备管理、文件管理,还是储存管理都离不开进程的管理。文件一般都需要存储,而文件的存储需要文件管理进行存储,也需要储存管理来对文件存储分配空间等等。3.
针对某一特定的应用环境,如何完善操作系统的功能?要想完善操作系统的功能,必须要合理安排各个功能模块,并利用有效的算法对各个功能进行管理和处理。任务二
进程管理【实训目的】掌握临界区的概念及临界区的设计原则;掌握信号量的概念、PV操作的含义以及应用PV操作实现进程的同步与互斥;分析进程争用资源的现象,学习解决进程互斥的方法;掌握进程的状态及状态转换;掌握常用的进程调度算法。【实训内容】1.分析进程的同步与互斥现象,编程实现经典的进程同步问题——生产者消费者问题的模拟;2.编写允许进程并行执行的进程调度程序,在常用的进程(作业)调度算法:先来先服务算法、短作业优先算法、最高响应比优先算法、高优先权优先算法等调度算法中选择一种调度算法进行简单模拟,并输出平均周转时间和平均带权周转时间。【实训步骤】一:生产者消费者问题的模拟1.分析与设计(详细分析设计,并给出流程图)
2.程序代码
#include<windows.h>#include<iostream>constunsignedshortSIZE_OF_BUFFER=10;//缓冲区长度unsignedshortProductID=0;//产品号unsignedshortConsumeID=0;//将被消耗的产品号unsignedshortin=0;//产品进缓冲区时的缓冲区下标unsignedshortout=0;//产品出缓冲区时的缓冲区下标intg_buffer[SIZE_OF_BUFFER];//缓冲区是个循环队列boolg_continue=true;//控制程序结束HANDLEg_hMutex;//用于线程间的互斥HANDLEg_hFullSemaphore;//当缓冲区满时迫使生产者等待HANDLEg_hEmptySemaphore;//当缓冲区空时迫使消费者等待DWORDWINAPIProducer(LPVOID);//生产者线程DWORDWINAPIConsumer(LPVOID);//消费者线程intmain(){//创建各个互斥信号g_hMutex=CreateMutex(NULL,FALSE,NULL);g_hFullSemaphore=CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL);g_hEmptySemaphore=CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);//调整下面的数值,可以发现,当生产者个数多于消费者个数时,//生产速度快,生产者经常等待消费者;反之,消费者经常等待constunsignedshortPRODUCERS_COUNT=3;//生产者的个数constunsignedshortCONSUMERS_COUNT=1;//消费者的个数//总的线程数constunsignedshortTHREADS_COUNT=PRODUCERS_COUNT+CONSUMERS_COUNT;HANDLEhThreads[PRODUCERS_COUNT];//各线程的handleDWORDproducerID[CONSUMERS_COUNT];//生产者线程的标识符DWORDconsumerID[THREADS_COUNT];//消费者线程的标识符//创建生产者线程for(inti=0;i<PRODUCERS_COUNT;++i){hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);if(hThreads[i]==NULL)return-1;}//创建消费者线程for(i=0;i<CONSUMERS_COUNT;++i){hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);if(hThreads[i]==NULL)return-1;}while(g_continue){if(getchar()){//按回车后终止程序运行g_continue=false;}}return0;}//生产一个产品。简单模拟了一下,仅输出新产品的ID号voidProduce(){std::cerr<<"生产一个产品"<<++ProductID<<"...";std::cerr<<"成功"<<std::endl;}//把新生产的产品放入缓冲区voidAppend(){std::cerr<<"把新生产的产品放入缓冲区...";g_buffer[in]=ProductID;in=(in+1)%SIZE_OF_BUFFER;std::cerr<<"成功"<<std::endl;//输出缓冲区当前的状态for(inti=0;i<SIZE_OF_BUFFER;++i){std::cout<<i<<":"<<g_buffer[i];if(i==in)std::cout<<"<--生产";if(i==out)std::cout<<"<--消费";std::cout<<std::endl;}}//从缓冲区中取出一个产品voidTake(){std::cerr<<"从缓冲区中取出一个产品...";ConsumeID=g_buffer[out];out=(out+1)%SIZE_OF_BUFFER;std::cerr<<"成功"<<std::endl;//输出缓冲区当前的状态for(inti=0;i<SIZE_OF_BUFFER;++i){std::cout<<i<<":"<<g_buffer[i];if(i==in)std::cout<<"<--生产";if(i==out)std::cout<<"<--消费";std::cout<<std::endl;}}//消耗一个产品voidConsume(){std::cerr<<"消耗一个产品"<<ConsumeID<<"...";std::cerr<<"成功"<<std::endl;}//生产者DWORDWINAPIProducer(LPVOIDlpPara){while(g_continue){WaitForSingleObject(g_hFullSemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Produce();Append();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hEmptySemaphore,1,NULL);}return0;}//消费者DWORDWINAPIConsumer(LPVOIDlpPara){while(g_continue){WaitForSingleObject(g_hEmptySemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Take();Consume();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hFullSemaphore,1,NULL);}return0;}3.运行并测试程序,并给出程序运行界面。二:先来先服务算法分析与设计(详细分析设计,并给出流程图)开始开始初始化pcb,输入进程信息各进程按先来先到的顺序进入就绪队列结束运行运行进程所需CPU时间撤消该进程就绪队列空?N2.程序代码#include<stdio.h>structfcfs{charname[10];//进程名称intprio;//priority进程优先数 floatarrivetime;//到达时间floatservicetime;//运行时间floatstarttime;//开始时间floatfinishtime;//完成时间floatzztime;//周转时间floatdqzztime;//带权周转时间};fcfsa[100];voidinput(fcfs*p,intN){inti;printf("输入进程名称&到达时间&运行时间&进程优先数:\nforexmple:a01001\n");for(i=0;i<=N-1;i++){ printf("输入%dth进程信息:\n",i+1);scanf("%s%f%f%d",&p[i].name,&p[i].arrivetime,&p[i].servicetime,&p[i].prio);}}voidPrint(fcfs*p,floatarrivetime,floatservicetime,floatstarttime,floatfinishtime,floatzztime,floatdqzztime,intprio,intN){ intk;printf("runorder:");printf("%s",p[0].name);for(k=1;k<N;k++){ printf("-->%s",p[k].name);}printf("\n进程信息:\n");printf("\nname\tarrive\tservice\tstart\tfinish\tzz\tdqzz\tprio\n");for(k=0;k<=N-1;k++){ printf("%s\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t%d\n",p[k].name,p[k].arrivetime,p[k].servicetime,p[k].starttime,p[k].finishtime,p[k].zztime,p[k].dqzztime,p[k].prio);}}//paixuvoidsort(fcfs*p,intN){for(inti=0;i<=N-1;i++)for(intj=0;j<=i;j++)if(p[i].arrivetime<p[j].arrivetime){fcfstemp;temp=p[i];p[i]=p[j];p[j]=temp;}}//yunxingjieduanvoiddeal(fcfs*p,floatarrivetime,floatservicetime,floatstarttime,floatfinishtime,float&zztime,float&dqzztime,intprio,intN){intk;for(k=0;k<=N-1;k++){if(p[k].arrivetime>p[k-1].finishtime){ p[k].starttime=p[k].arrivetime;p[k].finishtime=p[k].arrivetime+p[k].servicetime;}else{p[k].starttime=p[k-1].finishtime;p[k].finishtime=p[k-1].finishtime+p[k].servicetime;}}for(k=0;k<=N-1;k++){p[k].zztime=p[k].finishtime-p[k].arrivetime;p[k].dqzztime=p[k].zztime/p[k].servicetime;}}voidFCFS(fcfs*p,intN){floatarrivetime=0,servicetime=0,starttime=0,finishtime=0,zztime=0,dqzztime=0,prio=0;sort(p,N);deal(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,prio,N);Print(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,prio,N);}voidmain(){intN;printf("先来先服务调度算法\n");printf("输入进程数:\n");scanf("%d",&N);input(a,N);FCFS(a,N);}3.运行并测试程序,并给出程序运行界面。【思考题】针对某一具体应用环境,如何选择合适的调度算法?在批处理系统中,为了照顾为数众多的短作业,应采用短作业优先调度的调度算法;在分时系统中,为了保证系统具有合理的响应时间,应采用轮转法进行调度。非抢占式调度算法,有利于长作业,不利于短作业。【心得体会】通过这次实验了解到生产者-消费者问题是一个经典的进程同步问题,以及在其中使用信号量机制,生产者与消费者问题要求我们设计在同一个进程地址空间内执行的两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费,而消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。最简单的调度算法就是先来先服务,也可以称为先进先出(FirstInFirstOut)或严格排队方式。对于进程调度算法来说,先来先服务调度算法就是从就绪队列中选择一个最先进入队列的进程,将CPU分配于它,让其运行。该进程一直运行下去直到完成或由于某事件而被阻塞入放弃CPU。这样,当一个进程进入就绪队列时,它的PCB就链入了该就绪队列的末尾,排队等待分配CPU。一般来说,先来先服务调度算法对于长任务来说比较短任务要好一些。FCFS算法不考虑作业运行时间的长短,仅按作业进入输入井时间的先后进行调度,因此对所有的作业是公平合理的。 这次生产者和消费者问题、以及先来先服务调度算法的程序设计,不但加深了我对操作系统中多线程机制的理解和认识,更让我认识到知识的掌握,仅靠学习理论知识是远远不够的,要与实际动手操作相结合才能更好的理解和分析问题。任务三
存储管理【实训目的】掌握物理内存和虚拟内存的基本概念;掌握重定位的基本概念及其要点,理解逻辑地址与绝对地址;掌握各种存储管理的实现方法,包括基本原理、地址变换和缺页中断、主存空间的分配及分配算法;掌握常用淘汰算法。【实训内容】编写一个模拟的动态页式存储管理程序,实现对动态页式存储的淘汰算法的模拟(在先进先出淘汰算法、最近最少使用淘汰算法、最不经常使用淘汰算法三种算法中选择一种进行模拟)并计算各个算法的缺页率;并且页面淘汰算法在淘汰一页时,只将该页在页表中抹去,而不再判断它是否被改写过,也不将它写回到辅存【实训步骤】1.分析与设计(详细分析设计,并给出流程图)2.程序代码#include<iostream.h>#include<iomanip.h>#definem5//m表示页数#definen3//n表示物理块数floatinterrupt=0;//产生缺页中断的次数intk=0;//指向最先进入内存的页,即被淘汰的页intPageTable[m];//定义页表,总共m页,数组中数值是状态位=1表示该页在内存中,=0表示不在内存中,默认处置为0intBlock[n];//定义物理块,总共n个,数组中数值表示对应物理块中装入的页的编号intprocess[20];//进程访问序列intnumber=1;//用于标志访问次数voidVisit(int);//访问函数//主函数voidmain(void){intinput;cout<<"某进程共有"<<m<<"页,请输入进程访问序列(范围:1-"<<m<<",用0表示结束):\n";cin>>input;for(intlength=0;input!=0;length++)//将输入序列存入process数组,长度为length{process[length]=input;cin>>input;}for(intj=0;j<length;j++)Visit(process[j]);//依次访问页process[j]cout<<"共"<<length<<"次访问,产生"<<interrupt<<"次缺页中断,缺页率为"<<interrupt/length<<"\n";}//访问函数voidVisit(intx){inti,j;cout<<setw(2)<<number<<":访问页"<<x<<"";//第number次访问,访问页xfor(i=0;i<n;i++){if(Block[i]==0)//访问页x时没有命中,且内存未装满,产生缺页中断,直接调入访问页{interrupt++;//缺页中断次数加1PageTable[x-1]=1;//修改状态位Block[i]=x;//页x调入物理块cout<<"缺页中断内存未满调入页"<<x<<"物理块内的页为";for(j=0;j<=i;j++)cout<<Block[j]<<"";//输出物理块内的页号cout<<"\n";break;}if(PageTable[x-1]==1)//访问页x时命中{cout<<"命中物理块内的页为";for(j=0;j<n&&Block[j]!=0;j++)cout<<Block[j]<<"";//输出物理块内的页号cout<<"\n";break;}}if(i==n)//访问页x时内存已装满,且没有命中,产生缺页中断,调入该页至内存,淘汰最先进入的页{cout<<"缺页中断淘汰页"<<Block[k]<<"调入页"<<x<<"物理块内的页为";interrupt++;//缺页中断次数加1PageTable[Block[k]-1]=0;//页Block[k]被淘汰,状态位修改为0Block[k]=x;//页x调入物理块PageTable[x-1]=1;//页x状态位修改为1k=(k+1)%n;//修改下次被淘汰页指针for(j=0;j<n;j++)cout<<Block[j]<<"";//输出物理块内的页号cout<<"\n";}number++;//访问次数加1}3.运行并测试程序,并给出程序运行界面。【思考题】各种不同的页面淘汰算法有哪些优缺点?为什么会产生页面抖动?什么是belady象?这种现象该如何避免?最佳置换算法(Optimal)是一种理想化的算法,它具有最好的性能,但实际上却难于实现。先进先出置换算法(FIFO)是最直观的算法,由于它可能是性能最差的算法,故实际应用极少。最近最久未使用置换算法(LRU)虽然是一种比较好的算法,但要求系统有较多的支持硬件。因为刚被淘汰出去的页,过后不久又要访问它,需要再次调入,而调入后不久又再次被淘汰,然后又要访问,如此反复,使得系统的把大部分时间用在页面的调进调出上,这种形象称为“抖动”。随着物理块数的增多缺页率增大,从而造成Belady异常现象。尽量避免物理块数不断增多缺页率最大。【心得体会】通过这次实验,进一步了解了什么是缺页中断,以及处理缺页中断的调度算法。但是本程序有一个缺点在与物理块的页数相同的最前面几个数中不能出现0,否则会出现错误。因为由于在该程序中把0当作一种为空的标识符了,因而可能会造成缺页的统计出现错误,从而使缺页率也出错。本来我打算对该程序进行该进的,但由于时间很紧迫,没有改进了,希望大家见谅。但总得来说,通过本次编程,加深了我对理论学习的理解。任务四
设备管理【实训目的】掌握独占设备的使用方式,以及设备的分配和回收;掌握用死锁避免方法来处理申请独占设备可能造成的死锁。【实训内容】用死锁避免方法来处理申请独占设备可能造成的死锁,程序实现对银行家算法的模拟。【实训步骤】1、分析与设计(详细分析设计,并给出流程图)1.1、银行家算法:设进程i提出请求Request[n],则银行家算法按如下规则进行判断。(1)如果Request[n]>Need[i,n],则报错返回。(2)如果Request[n]>Available,则进程i进入等待资源状态,返回。(3)假设进程i的申请已获批准,于是修改系统状态:Available=Available-RequestAllocation=Allocation+RequestNeed=Need-Request(4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。1.2、安全性检查:(1)设置两个工作向量Work=Available;Finish[M]=False(2)从进程集合中找到一个满足下述条件的进程,Finish[i]=FalseNeed<=Work如找到,执行(3);否则,执行(4)(3)设进程获得资源,可顺利执行,直至完成,从而释放资源。Work=Work+AllocationFinish=TrueGOTO2(4)如所有的进程Finish[M]=true,则表示安全;否则系统不安全 1.3、
设计银行家算法的数据结构和基本定义:#defineM5//总进程数#defineN3//总资源数structbank//定义结构体{intAvailable[N];//可利用资源向量intMax[M][N];//最大需求矩阵intAllocation[M][N];//分配矩阵intNeed[M][N];};//需求矩阵voidInitilize(bank&);//初始化intSafe_test(bank);//检查安全性voidResoure_allocate(bank&);//系统对进程资源申请的处理voidmain(void);//主函数 1.4、分析银行家算法的实现过程,流程图如下图6所示:图6银行算法的实现流程2、程序代码:#include"string.h"#include<stdio.h>#include<stdlib.h>#defineM5//总进程数#defineN3//总资源数structbank//定义结构体{intAvailable[N];//可利用资源向量intMax[M][N];//最大需求矩阵intAllocation[M][N];//分配矩阵intNeed[M][N];//需求矩阵};voidInitilize(bank&);//初始化intSafe_test(bank);//检查安全性voidResoure_allocate(bank&);//系统对进程资源申请的处理voidmain(void){bankcurrent;//定义变量Initilize(current);//初始化Safe_test(current);//检查安全性while(1)//循环执行进程申请资源和系统对申请的处理{Resoure_allocate(current);}}voidInitilize(bank&x)//初始化{inti,j;printf("初始化过程,输入相关数据:\n");printf("输入最大需求矩阵Max:\n");for(i=0;i<M;i++)//设置最大需求矩阵{for(j=0;j<N;j++){scanf("%d",&x.Max[i][j]);}}printf("输入分配矩阵Allocation:\n");for(i=0;i<M;i++)//设置分配矩阵{for(j=0;j<N;j++){scanf("%d",&x.Allocation[i][j]);}}for(i=0;i<M;i++)//设置需求矩阵{for(j=0;j<N;j++){x.Need[i][j]=x.Max[i][j]-x.Allocation[i][j];}}printf("输入可利用资源向量:\n");for(i=0;i<N;i++)//设置可利用资源向量{scanf("%d",&x.Available[i]);}}intSafe_test(bankx)//检查安全性{inti,j;intsafeprocess[M];//安全序列向量intwork[N];//空闲资源矩阵intFinish[M];//进程完成标志矩阵for(i=0;i<N;i++)//开始时可利用资源向量就是空闲资源矩阵work[i]=x.Available[i];for(i=0;i<M;i++)//初始化标志矩阵为falseFinish[i]=false;intk=0;//安全序列排列号for(i=0;i<M;i++)//每次都从第一个进程开始做循环{if(Finish[i]==false){for(j=0;j<N;j++){if(x.Need[i][j]>work[j])//判断当前进程需求矩阵能否得到满足break;//不满足则跳出}if(j==N)//第i个进程满足执行条件{safeprocess[k++]=i;//将进程号存入安全序列向量for(intq=0;q<N;q++)//修改空闲资源矩阵work[q]+=x.Allocation[i][q];Finish[i]=true;//标志该进程可完成i=-1;//下次检查从第一个进程重新查起}}}for(i=0;i<M;i++)//检查标志数组,若有一个为false则找不到安全序列if(!Finish[i]){printf("找不到安全序列,系统处于不安全状态!\n");return0;}printf("找到安全序列:");//找到安全序列并显示该序列for(i=0;i<M;i++) printf("进程:%d",safeprocess[i]+1);printf("\n系统处于安全状态.\n");return1;}voidResoure_allocate(bank&x)//系统对进程资源申请的处理{banktemp=x;//临时变量存储x的初值intRequest[N];//请求向量intnumber;//进程号inti;printf("请输入要申请资源的进程序号:\n");scanf("%d",&number);printf("请输入请求向量:\n");for(i=0;i<N;i++) scanf("%d",&Request[i]);//输入请求向量for(i=0;i<N;i++){if(Request[i]>x.Need[number-1][i])//所需资源数大于需求量{printf("进程所需要的资源数已超过它所宣布的最大值,系统不予分配资源!\n");return;}if(Request[i]>x.Available[i])//所需资源数大于可利用资源{printf("系统中无足够的资源满足进程的申请,系统不予分配资源!\n");return;}}for(i=0;i<N;i++)//假设系统将申请资源数分配给该进程,对数据进行相关修改{x.Available[i]-=Request[i];x.Need[number-1][i]-=Request[i];x.Allocation[number-1][i]+=Request[i];}if(Safe_test(x))//安全性检查结果为安全{printf("系统可以为该进程分配资源.\n");return;}else//安全性检查结果为不安全{printf("系统不为该进程分配资源\n");x=temp;//将相关矩阵修改过来,表示资源不分配资源return;}}运行并测试程序,并给出程序运行界面:结果分析:数据来源于《计算机操作系统》(第三版)课本(1)、(2)、P2请求资源:P2发出请求向量Request(1,0,2)。【思考题】如果产生了死锁,应如何解除?当发现有进程死锁时,便应立即把它们从死锁状态中解脱出来。常采用解除死锁的两种方法是:(1)剥夺资源。从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态。(2)撤消进程。最简单的撤消进程的方法是使全部死锁进程都夭折掉;稍微温和一点的方法是按照某种顺序逐个地撤消进程,直至有足够的资源可用,使死锁状态消除为止。【心得体会】在避免死锁的方法中,允许进程动态地申请资源,系统在进行资源分配之前,先计算资源分配的安全性。若此次分配不会导致系统进入不安全状态,便将资源分配给进程,否则进程等待。银行家算法是死锁避免算法中的一种,通过上面这个例子,我们看到银行家算法确实能保证系统时时刻刻都处于安全状态,但它要不断检测每个进程对各类资源的占用和申请情况,需花费较多的时间。本次实验从整体上来说实验是比较成功的,也很自由——我们可以根据需要和要求,自由安排系统资源。由于时间仓促,做的不是很完美,敬请谅解。任务五
文件管理【实训目的】掌握文件的存取方法;掌握文件的逻辑结构和物理结构;掌握存储空间的分配和回收;掌握磁盘管理与调度。【实训内容】用程序模拟磁盘的调度过程,并计算各磁盘调度算法包括先来先服务算法、最短寻道时间优先算法、扫描算法和循环扫描算法的平均寻道长度。【实训步骤】1.分析与设计(详细分析设计,并给出流程图)1..先来先服务算法流程图输入当前磁道号now输入当前磁道号now磁头移动距离sum=abs(now-array[0])磁头移动总距离Sum+=abs(array[j]-array[i])输出磁盘调度序列array[j]目前的位置变为当前的位置j++j<m输出平均寻道长度avg=sum/(m)2.最短寻道时间优先算法流程图将磁道号从小到大排序将磁道号从小到大排序输入当前磁道号nowarray[m-1]<=now输出磁盘调度序列array[j]目前的位置变为当前的位置now=array[i]磁头移动总距离sum=now-array[i]i>=0输出磁盘调度序列array[j](array[0]>=now磁头移动总距离sum=now-array[i]目前的位置变为当前的位置now=array[i]now=array[i]i<m确定当前磁道在已排的序列中的位置now-array[l])<=(array[r]-now先向磁道号减小方向访问,再向磁道号增加方向访问输出磁盘调度序列先向磁道号增加方向访问,再向磁道号减小方向访问输出磁盘调度序列输出平均寻道长度avg=sum/(m)3.扫描算法流程图将磁道号从小到大排序将磁道号从小到大排序输入当前磁道号now,移动臂的移动的方向array[m-1]<=now磁头移动总距离sum=now-array[i]输出磁盘调度序列array[j]i>=0(array[0]>=now输出磁盘调度序列array[j]i<m磁头移动总距离sum=array[i]-now确定当前磁道在已排的序列中的位置switch(d)case0:移动臂向磁道号减小方向访问case1:移动臂向磁道号增加方向访问访问输出磁盘调度序列输出磁盘调度序列输出平均寻道长度avg=sum/(m)2.程序代码
#include"stdio.h"#include"stdlib.h"voidCopyL(intSour[],intDist[],intx);//数组Sour复制到数组Dist,复制到x个数voidSetDI(intDiscL[]);//随机生成磁道数voidPrint(intPri[],intx);//打印输出数组PrivoidDelInq(intSour[],intx,inty);//数组Sour把x位置的数删除,并把y前面的数向前移动,y后的数保持不变(即会出现2个y)voidFCFS(intHan,intDiscL[]);//先来先服务算法(FCFS)voidSSTF(intHan,intDiscL[]);//最短寻道时间优先算法(SSTF)intSCAN(intHan,intDiscL[],intx,inty);//扫描算法(SCAN)voidCSCAN(intHan,intDiscL[]);//循环扫描算法(CSCAN)voidN_Step_SCAN(intHan1,intDiscL[]);//N步扫描算法voidPaiXu();//寻道长度由低到高排序voidPri();intNAll=0;intBest[5][2];//用作寻道长度由低到高排序时存放的数组intLimit=0;//输入寻找的范围磁道数iintJage;floatAver=0;intfa5(){inti;intDiscLine[10];//声明准备要生成的随机磁道号的数组intHand;//磁道数intCon=1;intn;while(Con==1){Jage=0;printf("\n请输入初始的磁道数(0<n<65536):");scanf("%d",&Hand);printf("\n+输入寻找的范围:");scanf("%d",&Limit);if(Limit>65536){printf("超出范围!");}else{printf("1.先来先服务算法(FCFS)\n");printf("2.最短寻道时间优先算法(SSTF)\n");printf("3.扫描算法(SCAN)\n");printf("4.循环扫描算法(CSCAN)\n");printf("5.N步扫描算法(NStepScan)\n");printf("6.各类算法的比较\n");printf("请输入你的选择的算法(输入0离开)\n");scanf("%d",&n);if(n==0)exit(0);printf("\n");switch(n){case1:SetDI(DiscLine);//随机生成磁道数FCFS(Hand,DiscLine);//先来先服务算法(FCFS)break;case2:SetDI(DiscLine);//随机生成磁道数SSTF(Hand,DiscLine);//最短寻道时间优先算法(SSTF)break;case3:SetDI(DiscLine);//随机生成磁道数SCAN(Hand,DiscLine,0,9);//扫描算法(SCAN)break;case4:SetDI(DiscLine);//随机生成磁道数CSCAN(Hand,DiscLine);//循环扫描算法(CSCAN)break;case5:SetDI(DiscLine);//随机生成磁道数N_Step_SCAN(Hand,DiscLine);//N步扫描算法(NStepScan)break;case6:SetDI(DiscLine);//随机生成磁道数FCFS(Hand,DiscLine);//先来先服务算法(FCFS)SSTF(Hand,DiscLine);//最短寻道时间优先算法(SSTF)SCAN(Hand,DiscLine,0,9);//扫描算法(SCAN)CSCAN(Hand,DiscLine);//循环扫描算法(CSCAN)N_Step_SCAN(Hand,DiscLine);//N步扫描算法(NStepScan)PaiXu();//寻道长度由低到高排序printf("\n\n+寻道长度由低到高排序:");for(i=0;i<5;i++){printf("%4d",Best[i][0]);}break;}printf("\n\n+是否继续(按0结束,按1继续)?");scanf("%5d",&Con);}}return0;}//数组Sour复制到数组Dist,复制到x个数voidCopyL(intSour[],intDist[],intx){inti;for(i=0;i<=x;i++){Dist[i]=Sour[i];}}//打印输出数组PrivoidPrint(intPri[],intx){inti;for(i=0;i<=x;i++){printf("%5d",Pri[i]);}}//随机生成磁道数voidSetDI(intDiscL[]){inti;for(i=0;i<=9;i++){DiscL[i]=rand()%Limit;//随机生成10个磁道号}printf("+需要寻找的磁道号:");Print(DiscL,9);//输出随机生成的磁道号printf("\n");}//数组Sour把x位置的数删除,并把y前面的数向前移动,y后的数保持不变(即会出现2个y)voidDelInq(intSour[],intx,inty){inti;for(i=x;i<y;i++){Sour[i]=Sour[i+1];x++;}}//先来先服务算法(FCFS)voidFCFS(intHan,intDiscL[]){intRLine[10];//将随机生成的磁道数数组Discl[]复制给数组RLine[]inti,k,All,Temp;//Temp是计算移动的磁道距离的临时变量All=0;//统计全部的磁道数变量k=9;//限定10个的磁道数CopyL(DiscL,RLine,9);//复制磁道号到临时数组RLineprintf("\n+按照FCFS算法磁道的访问顺序为:");All=Han-RLine[0];for(i=0;i<=9;i++){Temp=RLine[0]-RLine[1];//求出移动磁道数,前一个磁道数减去后一个磁道数得出临时的移动距离if(Temp<0)Temp=(-Temp);//移动磁道数为负数时,算出相反数作为移动磁道数printf("%5d",RLine[0]);All=Temp+All;//求全部磁道数的总和DelInq(RLine,0,k);//每个磁道数向前移动一位k--;}Best[Jage][1]=All;//Best[][1]存放移动磁道数Best[Jage][0]=1;//Best[][0]存放算法的序号为:1Jage++;//排序的序号加1Aver=((float)All)/10;//求平均寻道次数printf("\n+移动磁道数:<%5d>",All);printf("\n+平均寻道长度:*%0.2f*",Aver);}//最短寻道时间优先算法(SSTF)voidSSTF(intHan,intDiscL[]){inti,j,k,h,All;intTemp;//Temp是计算移动的磁道距离的临时变量intRLine[10];//将随机生成的磁道数数组Discl[]复制给数组RLine[]intMin;All=0;//统计全部的磁道数变量k=9;//限定10个的磁道数CopyL(DiscL,RLine,9);//复制磁道号到临时数组RLineprintf("\n+按照SSTF算法磁道的访问顺序为:");for(i=0;i<=9;i++){Min=64000;for(j=0;j<=k;j++)//内循环寻找与当前磁道号最短寻道的时间的磁道号{if(RLine[j]>Han)//如果第一个随机生成的磁道号大于当前的磁道号,执行下一句Temp=RLine[j]-Han;//求出临时的移动距离elseTemp=Han-RLine[j];//求出临时的移动距离if(Temp<Min)//如果每求出一次的移动距离小于Min,执行下一句{Min=Temp;//Temp临时值赋予Minh=j;//把最近当前磁道号的数组下标赋予h}}All=All+Min;//统计一共移动的距离printf("%5d",RLine[h]);Han=RLine[h];DelInq(RLine,h,k);//每个磁道数向前移动一位k--;}Best[Jage][1]=All;//Best[][1]存放移动磁道数Best[Jage][0]=2;//Best[][0]存放算法的序号为:2Jage++;//排序序号加1Aver=((float)All)/10;//求平均寻道次数printf("\n+移动磁道数:<%5d>",All);printf("\n+平均寻道长度:*%0.2f*",Aver);}//扫描算法(SCAN)intSCAN(intHan,intDiscL[],intx,inty){intj,n,k,h,m,All;intt=0;intTemp;intMin;intRLine[10];//将随机生成的磁道数数组Discl[]复制给数组RLine[]intOrder;Order=1;k=y;m=2;//控制while语句的执行,即是一定要使当前磁道向内向外都要扫描到All=0;//统计全部的磁道数变量CopyL(DiscL,RLine,9);//复制磁道号到临时数组RLineprintf("\n+按照SCAN算法磁道的访问顺序为:");Min=64000;for(j=x;j<=y;j++)//寻找与当前磁道号最短寻道的时间的磁道号{if(RLine[j]>Han)//如果第一个随机生成的磁道号大于当前的磁道号,执行下一句Temp=RLine[j]-Han;//求出临时的移动距离elseTemp=Han-RLine[j];//求出临时的移动距离if(Temp<Min){Min=Temp;//Temp临时值赋予Minh=j;//把最近当前磁道号的数组下标赋予h}}All=All+Min;printf("%5d",RLine[h]);if(RLine[h]>=Han){//判断磁道的移动方向,即是由里向外还是由外向里Order=0;t=1;}Han=RLine[h];DelInq(RLine,h,k);//每个磁道数向前移动一位k--;while(m>0){if(Order==1)//order是判断磁盘扫描的方向标签,order是1的话,磁道向内移动{for(j=x;j<=y;j++){h=-1;Min=64000;for(n=x;n<=k;n++)//判断离当前磁道最近的磁道号{if(RLine[n]<=Han){Temp=Han-RLine[n];if(Temp<Min){Min=Temp;//Temp临时值赋予Minh=n;//把最近当前磁道号的数组下标赋予h}}}if(h!=-1){All=All+Min;//叠加移动距离printf("%5d",RLine[h]);Han=RLine[h];//最近的磁道号作为当前磁道DelInq(RLine,h,k);k--;}}Order=0;//当完成向内的移动,order赋予0,执行else语句,使磁道向外移动m--;//向内完成一次,m减一次,保证while循环执行两次}else//order是0的话,磁道向外移动{for(j=x;j<=y;j++){h=-1;Min=64000;for(n=x;n<=k;n++)//判断离当前磁道最近的磁道号{if(RLine[n]>=Han){Temp=RLine[n]-Han;if(Temp<Min){Min=Temp;//Temp临时值赋予Minh=n;//把最近当前磁道号的数组下标赋予h}}}if(h!=-1){All=All+Min;//叠加移动距离printf("%5d",RLine[h]);Han=RLine[h];//最近的磁道号作为当前磁道DelInq(RLine,h,k);k--;}}Order=1;//当完成向内的移动,order赋予0,执行else语句,使磁道向外移动m--;//向内完成一次,m减一次,保证while循环执行两次}}NAll=NAll+All;if((y-x)>5){Best[Jage][1]=All;//Best[][1]存放移动磁道数Best[Jage][0]=3;//Best[][0]存放算法的序号为:3Jage++;//排序序号加1Aver=((float)All)/10;//求平均寻道次数printf("\n+移动磁道数:<%5d>",All);printf("\n+平均寻道长度:*%0.2f*",Aver);}if(t==1)printf("\n+磁道由内向外移动");elseprintf("\n+磁道由外向内移动");return(Han);}//循环扫描算法(CSCAN)voidCSCAN(intHan,intDiscL[]){intj,h,n,Temp,m,k,All,Last,i;intRLine[10];//将随机生成的磁道数数组Discl[]复制给数组RLine[]intMin;inttmp=0;m=2;k=9;All=0;//统计全部的磁道数变量Last=Han;CopyL(DiscL,RLine,9);//复制磁道号到临时数组RLineprintf("\n+按照CSCAN算法磁道的访问顺序为:");while(k>=0){for(j=0;j<=9;j++)//从当前磁道号开始,由内向外搜索离当前磁道最近的磁道号{h=-1;Min
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- Thioredoxin-Reductase-NADPH-Yeast-生命科学试剂-MCE
- 零售门店员工绩效考评表
- 绿化环保宣传企业制定与实施新质生产力战略分析报告
- 片状叔胺行业盈利模式创新与变革分析报告
- 2025-2030年耐火材料烧结工艺行业深度调研及发展战略咨询报告
- 中医特色护理在康复护理中的应用
- 乙型流感护理中的病情观察
- 安全与健康标准遵守情况绩效考核表
- 儿童急性荨麻疹的特别护理注意事项
- 儿童听力保健护理查房
- 2026年宣城广德市大学生乡村医生专项计划招聘3名考试参考题库及答案详解
- GB/T 47651-2026温室气体产品碳足迹量化方法与要求光热发电
- 2026中国光纤行业安全生产标准与风险管理体系研究报告
- 高温天户外劳动者休息驿站建设
- 2026版数据资产入表工作底稿清单与权属确认表流程表单模板
- 乳胶漆涂刷质量保证措施
- 2026新疆安全员C1证考试题库(附答案)
- 医院学科带头人选拔培养管理办法
- 小升初语文拼音与汉字专项练习(含解析)
- 作业标准培训教材
- 2型糖尿病诊疗指南(2026年版)基层规范化治疗
评论
0/150
提交评论