OS课设之CPU调度算法的模拟实现
- 格式:doc
- 大小:82.00 KB
- 文档页数:24
操作系统实验⼀:处理器调度算法的实现(1)加深对处理机调度的作⽤和⼯作原理的理解。
(2)进⼀步认识并发执⾏的实质。
⼆、实验要求:本实验要求⽤⾼级语⾔,模拟在单处理器情况下,采⽤多个调度算法,对N个进程进⾏进程调度。
语⾔⾃选。
并完成实验报告。
三、实验内容:在采⽤多道程序设计的系统中,往往有若⼲个进程同时处于就绪状态。
当就绪状态进程个数⼤于处理器数时,就必须依照某种策略来决定哪些进程优先占⽤处理器。
1. 进程及进程队列的表⽰。
2. 处理器调度算法:FCFS,SJF,RR,HRRN,MLFQ等3. 跟踪进程状态的转化4. 输出:系统中进程的调度次序,计算CPU利⽤率,平均周转时间和平均带权周转时间四、实验过程与结果 1.先来先服务调度算法(FCFS) 1.1算法思想 该算法采⽤⾮剥夺策略,算法按照进程提交或进程变为就绪状态的先后次序,分派 CPU。
当前进程占⽤CPU,直到执⾏完或阻塞,才出让CPU(⾮抢占⽅式)。
在进程唤醒后(如I/O 完成),并不⽴即恢复执⾏,通常等到当前进程出让CPU。
这是最简单的调度算法,⽐较有利于长进程,⽽不利于短进程,有利于CPU 繁忙的进程,⽽不利于I/O 繁忙的进程。
1.2算法设计 1.3算法实现代码class Process:def__init__ (self,name,arrive_time,serve_time):=nameself.arrive_time=arrive_time #进⼊进程顺序self.serve_time=serve_time #服务时间self.finish_time=0 #完成时间self.cycling_time=0 #周转时间self.w_cycling_time=0 #带权周转时间process_list=[]running_time=0A = Process('A',5,4)B = Process('B',4,3)C = Process('C',3,4)D = Process('D',1,2)E = Process('E',2,4)process_list.append(A)process_list.append(B)process_list.append(C)process_list.append(D)process_list.append(E)i=int (0)p=process_list[i]y=len(process_list)print("进程进⾏排序")for j in range(len(process_list)-1):for k in range(len(process_list)-1):if process_list[k].arrive_time>process_list[k+1].arrive_time:text=process_list[k+1]process_list[k+1]=process_list[k]process_list[k]=textprint("进程号到达顺序服务时间")for p in process_list:print(, "\t" ,p.arrive_time,"\t" ,p.serve_time)for p in process_list:running_time +=p.serve_timep.finish_time=running_timep.cycling_time=p.finish_time-p.arrive_timep.w_cycling_time=p.cycling_time/p.serve_timeprint("进程号到达时间完成时间周转时间带权周转时间")for p in process_list:print( ,"\t\t",p.arrive_time,"\t\t\t\t",p.finish_time,"\t\t",p.cycling_time,"\t",p.w_cycling_time) 1.4运⾏结果 2.短作业优先算法(SJF) 2.1算法思想 该算法也采⽤⾮剥夺策略,对预计执⾏时间短的进程优先分派处理机。
课程设计报告设计名称:模拟实现一种处理机调度算法学生姓名: xxx专业:计算机科学与技术班别: xxxxxxxx 学号: xxxxxx 指导老师: xxxxx日期: 2014 年 6 月 20 日初始条件:1.预备内容:阅读操作系统的处理机管理章节内容,对进程调度的功能以及进程调度算法有深入的理解。
2.实践准备:掌握一种计算机高级语言的使用。
要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1.模拟进程调度,能够处理以下的情形:⑴能够选择不同的调度算法(要求中给出的调度算法);⑵能够输入进程的基本信息,如进程名、优先级、到达时间和运行时间等;⑶根据选择的调度算法显示进程调度队列;⑷根据选择的调度算法计算平均周转时间和平均带权周转时间。
2.设计报告内容应说明:⑴需求分析;⑵功能设计(数据结构及模块说明);⑶开发平台及源程序的主要部分;⑷测试用例,运行结果与运行情况分析;⑸自我评价与总结:i)你认为你完成的设计哪些地方做得比较好或比较出色;ii)什么地方做得不太好,以后如何改正;iii)从本设计得到的收获(在编写,调试,执行过程中的经验和教训);iv)完成本题是否有其他方法(如果有,简要说明该方法);进程调度模拟设计——先来先服务、优先级法1、背景:当计算机系统是多道程序设计系统时,通常会有多个进程或线程同时竞争CPU。
只要有两个或更多的进程处于就绪状态,这种情形就会发生。
如果只有一个CPU可用,那么就必须选择下一个要运行的进程。
在操作系统中,完成选择工作的这一部分称为调度程序,该程序使用的算法成为调度算法。
进程调度的核心问题是采用什么样的算法把处理机分配给进程,好的算法将提高资源利用率,减少处理机的空闲时间,避免有些作业长期得不到相应的情况发生等,从而设计出受欢迎的操作系统。
较常见的几种进程调度算法有:先来先服务调度算法;短作业优先调度算法;时间片轮转调度算法;优先级调度算法;高响应比优先算法和多级反馈队列调度算法等。
操作系统进程调度算法模拟实验报告一、实验目的本实验旨在深入理解操作系统的进程调度算法,并通过模拟实验来探究不同调度算法之间的差异和优劣。
二、实验原理操作系统的进程调度算法是决定进程执行顺序的重要依据。
常见的调度算法有先来先服务(FCFS)、最短作业优先(SJF)、优先级调度(Priority Scheduling)、轮转法(Round Robin)和多级反馈队列调度(Multilevel Feedback Queue Scheduling)等。
1.先来先服务(FCFS)算法:按照进程到达的先后顺序进行调度,被调度的进程一直执行直到结束或主动阻塞。
2.最短作业优先(SJF)算法:按照进程需要的执行时间的短长程度进行调度,执行时间越短的进程越优先被调度。
3. 优先级调度(Priority Scheduling)算法:为每个进程分配一个优先级,按照优先级从高到低进行调度。
4. 轮转法(Round Robin)算法:将进程按照到达顺序排列成一个队列,每个进程被分配一个时间片(时间量度),当时间片结束时,将进程从队列头取出放置到队列尾。
5.多级反馈队列调度算法:将进程队列分为多个优先级队列,每个队列时间片大小依次递减。
当一个队列中的进程全部执行完毕或者发生阻塞时,将其转移到下一个优先级队列。
三、实验步骤与结果1.实验环境:- 操作系统:Windows 10- 编译器:gcc2.实验过程:(1)首先,设计一组测试数据,包括进程到达时间、需要的执行时间和优先级等参数。
(2)根据不同的调度算法编写相应的调度函数,实现对测试数据的调度操作。
(3)通过模拟实验,观察不同调度算法之间的区别,比较平均等待时间、完成时间和响应时间的差异。
(4)将实验过程和结果进行记录整理,撰写实验报告。
3.实验结果:这里列举了一组测试数据和不同调度算法的结果,以便对比分析:进程,到达时间,执行时间,优先------,----------,----------,-------P1,0,10,P2,1,1,P3,2,2,P4,3,1,P5,4,5,a.先来先服务(FCFS)算法:平均等待时间:3.8完成时间:15b.最短作业优先(SJF)算法:平均等待时间:1.6完成时间:11c. 优先级调度(Priority Scheduling)算法:平均等待时间:2.8完成时间:14d. 轮转法(Round Robin)算法:时间片大小:2平均等待时间:4.8完成时间:17e.多级反馈队列调度算法:第一级队列时间片大小:2第二级队列时间片大小:4平均等待时间:3.8完成时间:17四、实验总结通过上述的实验结果可以得出以下结论:1.在上述测试数据中,最短作业优先(SJF)算法的平均等待时间最短,说明该算法在短作业的情况下能够有效地减少等待时间。
处理机调度算法的模拟在计算机操作系统中,处理机调度算法决定了在多个进程或任务同时存在的情况下,哪个任务将获得处理机的使用权,以及在多个任务之间如何切换。
处理机调度算法可以按照多个指标进行优化,例如响应时间、吞吐量、周转时间和等待时间等。
以下是几种常见的处理机调度算法:1.先来先服务(FCFS):先来先服务是最简单的调度算法之一,它按照任务到达的先后顺序分配处理机资源。
这种算法的优点是简单易实现,但是当存在长作业(任务)时,会导致其他短作业的等待时间过长。
2.短作业优先(SJF):短作业优先调度算法根据任务的估计执行时间来进行调度,优先执行估计执行时间短的任务。
这种算法可以减少任务的等待时间,但对于长作业来说,可能会导致饥饿现象。
3.优先级调度:优先级调度算法根据任务的优先级进行调度,优先级高的任务先获得处理机的使用权。
这种算法可以根据不同任务的紧急性和重要性来确保任务得到适当的优先级处理。
但是,如果优先级设置不合理,可能会导致一些任务永远得不到执行。
4.时间片轮转调度:时间片轮转调度算法是一种公平的调度算法,它将处理机的使用权按照时间片划分给不同的任务,每个任务只能执行一个时间片的任务。
如果任务在时间片结束之前没有完成,它将被放回到任务队列的末尾继续等待。
这种算法可以确保每个任务都有机会获得处理机的使用权,但是可能会存在上下文切换的开销。
以上只是几种常见的处理机调度算法,实际上还有许多其他算法以及它们的变体,例如最短剩余时间优先(SRTF)、多级反馈队列调度(MFQ)等。
每种调度算法都有不同的优缺点,选择适合的调度算法取决于系统的需求和资源限制。
为了模拟处理机调度算法,可以使用计算机模拟软件或编写自己的模拟程序。
模拟程序可以模拟任务的到达和执行过程,按照指定的调度算法进行任务的分配和切换,并统计不同指标(如响应时间、吞吐量等)来评估算法的性能。
在模拟处理机调度算法时,需要考虑以下几个方面:1.任务的到达过程:任务可以按照随机分布的方式到达,模拟任务的到达时间和资源需求。
课程实验报告
在单处理机的情况下模拟用优先权的时间片轮转调度策略实现处理机调度,以加深了解处理机调度的工作过程。
要求:
可利用先来先服务、短作业优先、响应比高者优先、多级反馈队列模型、时间片轮转法等,来实现处理机的调度。
根据单处理机,多任务的问题特性做好软件实现的需求分析。
可根据问题的实际需要,可选择进程数量。
当系统运行时,能直观地、动态地反映当前处理机状态及各进程执行的状况。
描述6.create函数用于创建队列
7.insert为插入函数,用于将一个时间片运行结束的进程插入到就绪进程的
队尾
8.priority函数:如果有进程就绪,就将处理机分配给该进程让他执行。
调试过程及实验结果
总结每次运行一步,电脑将会将该时刻所有进程控制块的运行状态显示给用户。
包括进程名、要求运行时间、已经运行时间、还需要运行时间、状态等信息。
当每个进程运行一个时间片之后将它从该队列中移除,添加到就绪队列队尾中以便使每个进程可以循环执行。
当要求运行时间和已运行时间相等时,说明该进程运行结束,将该进程撤出该队列并且不再添加到就绪队列中。
直到就绪队列中没有就绪进程为止
附录#define _CRT_SECURE_NO_DEPRECATE #include"stdio.h"
#include"stdlib.h"
#include"string.h"
typedef struct node
{
char pname[10]; //进程名
int rtime; //已运行时间
int sytime; //剩余时间。
实验一 进程调度算法模拟,1.内容:设计一个简单的进程调度算法,模拟OS 中的进程调度过程; 2.要求:① 进程数不少于5个;② 进程调度算法任选;可以用动态优先数加时间片轮转法实现进程调度,每运行一个时间片优先数减3; ③ 用C 语言编程;④ 程序运行时显示进程调度过程。
3.步骤:① 设计PCB 及其数据结构: 进程标识数:ID进程优先数:PRIORITY (优先数越大,优先级越高)进程已占用时间片:CPUTIME ,每得到一次调度,值加1;进程还需占用时间片:ALLTIME ,每得到一次调度,该值减1,一旦运行完毕,ALLTIME 为0)进程队列指针:NEXT ,用来将PCB 排成队列 进程状态:STA TE (一般为就绪,可以不用) ② 设计进程就绪队列及数据结构;③ 设计进程调度算法,并画出程序流程图; ④ 设计输入数据和输出格式;结构格式:当前正运行的进程:0当前就绪队列:2,1,3,4 ⑤ 编程上机,验证结果。
4.提示:假设调度前,系统中有5个进程,其初始状态如下: ID 0 1 2 3 4PRIORITY 9 38 30 29 0 可否考虑用数组或链表去实现CPUTIME 0 0 0 0 0 ALLTIME326 3 4 STA TE ready ready readyreadyready① 以时间片为单位调度运行;② 每次调度ALLTIME 不为0,且PRIORITY 最大的进程运行一个时间片;③ 上述进程运行后其优先数减3,再修改其CPUTIME 和ALLTIME ,重复②,③ ④ 直到所有进程的ALLTIME 均变为0。
5.书写实验报告 ① 实验题目;② 程序中所用数据结构及说明; ③ 清单程序及描述; ④ 执行结果。
操作系统实验一报告一.实验内容选择一个调度算法,实现处理器调度。
二.实验目的在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态。
当就绪状态进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。
本实验模拟在单处理器情况下处理器调度,帮助学生加深了解处理器调度的工作。
三.实验要求设计一个按优先数调度算法实现处理器调度的进程。
YNY上面的过程只给出了 那个寻找以及排序的大体过程,具体的过程太多画不下。
寻找优先级最高节点是否最高优先级优先数减一 运行时间减一继续寻找节点 运行时间是否为0删除节点 按优先级重新排序四.实验程序这个实验的程序使用的visual studio 2008 的c++ win控制台写的,所以可能老师的电脑里面。
我把程序结果贴在后面,还有第二题我也做了,但只要求写一个,那么。
// 操作系统实验.cpp : 定义控制台应用程序的入口点。
//#include"stdafx.h"#include<iostream>#include<string>using namespace std;static int num=0;class proc{private: string procname;proc * next;int time;int priority;char state;public:proc(){proc*next=new proc();}proc(string pr,proc * ne,int ti,int pri,char st):procname(pr),next(ne),time(ti),priority(pri),state(st){}~proc(){}void setnext(proc * n){next=n;}void setprocname(string s){procname=s;}void settime(int t){time=t;}void setpriority(int s){priority=s;}void setstate(char s){state=s;}proc * getnext(){return next;}string getprocname(){return procname;}int gettime(){return time;}int getpriority(){return priority;}char getstate(){return state;}};class dui{private:proc * first;public:dui(){first=new proc();}dui(proc*f){ first=f;}int getfirst_time(){return first->gettime();}void show(proc*p){cout<<"名字"<<"下个节点的名字"<<" "<<"时间"<<"优先级"<<"状态"<<endl;while(p){cout<<p->getprocname ()<<" "<<((p->getnext()!=NULL)?p->getnext ()->getprocname ():"NU")<<" "<<p->gettime ()<<" "<<p->getpriority()<<" "<<((p->gettime ()!=0)?p->getstate():'E')<<endl;p=p->getnext ();}cout<<"..............................................................."<<endl;}void process1(){proc*pp=first;show(first);while( first->getnext ()!=NULL){proc*pp_next=pp->getnext ();int a,b;a=pp->getpriority()-1;b=pp->gettime()-1;pp->setpriority(a);pp->settime(b);if(b==0){show(pp);pp =first=first->getnext ();continue;}int prio1,prio2;prio2=first->getnext ()->getpriority();prio1=pp->getpriority();if(prio1>=prio2){show(pp); }else{while(prio1<prio2){first=first->getnext ();if(first->getnext ()==NULL){first->setnext (pp);pp->setnext (NULL);break;}else prio2=first->getnext ()->getpriority(); }if(prio1>=prio2){pp->setnext (first->getnext ());first->setnext (pp);show(pp_next);}if(pp->getnext ()==NULL){show(pp_next); }pp=pp_next;first=pp;}}if(first->getnext ()==NULL)while(first->gettime()>0){int t=first->gettime()-1;first->settime(t);show(first);cout<<"五";}}};int main(){proc * A=new proc("p1",NULL,2,1,'R');proc * B=new proc("p2",NULL,3,5,'R');proc * C=new proc("p3",NULL,1,3,'R');proc * D=new proc("p4",NULL,2,4,'R');proc * E=new proc("p5",NULL,4,2,'R');B->setnext (D);D->setnext (C);C->setnext (E);E->setnext (A);dui aaa(B);//aaa.setfirst (B);aaa.process1 ();cin.get();return 0 ;}五.实验结果六.实验总结这个说来惭愧啊,因为自己的这个程序早就做好了,就是对进程啊什么的还不是很了解,因为自己不是学习认真的那一种,这个老师的那些问题把我给郁闷了好多天啊!悲剧!以后还是要好好学习,课后不能再玩得那么狠了!通过这个程序,我体会到了些程序前先把图给画出来是都么好的习惯啊!以后要多多用!还有我的电脑因为不知道什么病毒,c盘重还原了一下,原来在桌面的那个报告比这个更详细,这次因为不能上传加上自己没有保存就丢失了那个报告,临时写的这个希望老师不要怪我!!最后希望老师弄一下,最起码我们可以在机房里上传到ftp中!!!。
操作系统实验一处理机调度算法的实现操作系统中的处理机调度算法是为了合理地分配和利用处理器资源,提高系统的性能和响应速度。
这些算法主要用于决定下一个要执行的进程或线程。
在本篇文章中,我们将介绍几种常见的处理机调度算法以及它们的实际应用。
首先,我们要了解什么是处理机调度算法。
处理机调度是指从就绪队列中选择一个进程,并分配处理机给它。
调度算法的目标是合理地选择进程,以达到最佳的系统性能指标。
这些指标可以包括响应时间、吞吐量、公平性等。
最简单的调度算法是先来先服务(FCFS)。
这种算法按照进程到达的顺序来进行调度。
当一个进程完成后,下一个进程在队列头被选中执行。
FCFS算法的优点是实现简单,但缺点是不考虑进程的执行时间,导致平均等待时间较长。
FCFS主要用于批处理环境中,例如打印任务的排队。
另一种常见的调度算法是短作业优先(SJF)。
这种算法选择剩余执行时间最短的进程进行调度。
为了实现SJF算法,系统需要预测进程的执行时间,这可能是一个难题。
SJF算法的优点是能够最小化平均等待时间,但缺点是可能导致长作业的饥饿。
SJF算法主要用于交互式系统或具有预测性能的任务。
另一个常见的调度算法是轮转调度(RR)。
这种算法将处理机时间分成一定大小的时间片(时间片就是一段处理器运行的时间),每个进程在一个时间片内执行,然后进入队列尾部等待。
轮转调度算法的目的是实现公平性,每个进程都有机会被执行。
RR算法的优点是能够减少各个进程的响应时间,但缺点是可能造成高负载下的处理机浪费。
RR算法主要用于实时系统或多用户环境。
另一个调度算法是最高响应比优先(HRRN)。
响应比是指进程等待时间与预计执行时间的比率。
HRRN算法选择响应比最高的进程进行调度。
这种算法考虑了等待时间和执行时间的权衡,能够实现较好的性能。
但是,HRRN算法计算响应比需要实时监测和更新进程的等待时间和执行时间。
HRRN算法适用于交互式或多用户系统。
还有一种常见的调度算法是最短剩余时间优先(SRTF)。
南通大学计算机学院操作系统课程设计报告书设计题目处理器调度算法模拟专业班级软嵌161学生姓名候玉权学号**********指导教师丁红日期2018.07.05实验报告正文内容1、课程设计的目的在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态。
当就绪状态进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。
本实验模拟在单处理器情况下处理器调度,帮助学生加深了解处理器调度的工作。
2、课程设计的要求用C++语言编写程序完成单处理机的进程调度3、课程设计的环境在机房完成,运行环境vs20174、问题描述对cpu调度算法进行模拟实现,包含先来先服务,短作业优先,响应比最高优先,时间片轮转等算法。
5、算法分析数据结构struct ef{char name[10]; //进程名称int number; //进程编号float daodatime; //到达时间float kaishitime; //开始运行时间float yunxingtime; //运行时间float jieshutime; //运行结束时间int shengyutime; // 剩余时间int fuwutime; //服务时间int order; //运行次序int run_flag; //调度标志int priority; //优先级struct ef *next;}先来先服务算法int fcfs() //先来先服务{float tp = 0;int i;int zx;tp = ef[0].daodatime;for (i = 0; i<c; i++){ef[i].kaishitime = tp;ef[i].jieshutime = ef[i].kaishitime + ef[i].yunxingtime;ef[i].run_flag = 1;tp = ef[i].jieshutime;zx = i;ef[zx].order = i + 1;}return 0;}短作业优先int sjf() //短作业优先{float temp_time = 0;int i = 0, j;int zx, tc;float yunxingtime;yunxingtime = ef[i].yunxingtime;j = 1;while ((j<c) && (ef[i].daodatime == ef[j].daodatime)){if (ef[j].yunxingtime<ef[i].yunxingtime){yunxingtime = ef[j].yunxingtime;i = j;}j++;} //查找第一个被调度的进程//对第一个被调度的进程求相应的参数zx = i;ef[zx].kaishitime = ef[zx].daodatime;ef[zx].jieshutime = ef[zx].kaishitime + ef[zx].yunxingtime;ef[zx].run_flag = 1;temp_time = ef[zx].jieshutime;ef[zx].order = 1;tc = 1;while (tc<c){for (j = 0; j<c; j++){if ((ef[j].daodatime <= temp_time) && (!ef[j].run_flag)){yunxingtime = ef[j].yunxingtime; zx = j; break;}}for (j = 0; j<c; j++){if ((ef[j].daodatime <= temp_time) && (!ef[j].run_flag))if (ef[j].yunxingtime<yunxingtime){yunxingtime = ef[j].yunxingtime;zx= j;}}//查找下一个被调度的进程//对找到的下一个被调度的进程求相应的参数ef[zx].kaishitime = temp_time;ef[zx].jieshutime = ef[zx].kaishitime + ef[zx].yunxingtime;ef[zx].run_flag = 1;temp_time = ef[zx].yunxingtime;tc++;ef[zx].order = tc;}return 0;}响应比高优先int hrrf() //响应比高优先{int j, zx, tc;float temp_time, respond_rate, max_respond_rate;//第一个进程被调度ef[0].kaishitime = ef[0].daodatime;ef[0].jieshutime = ef[0].kaishitime + ef[0].yunxingtime;temp_time = ef[0].jieshutime;ef[0].run_flag = 1;ef[0].order = 1;tc = 1;//调度其他进程while (tc<c){max_respond_rate = 0;for (j = 1; j<c; j++){if ((ef[j].daodatime <= temp_time) && (!ef[j].run_flag)){respond_rate = (temp_time - ef[j].daodatime) / ef[j].yunxingtime;if (respond_rate>max_respond_rate){max_respond_rate = respond_rate;zx = j;}}}//找响应比高的进程ef[zx].kaishitime = temp_time;ef[zx].jieshutime = ef[zx].kaishitime + ef[zx].yunxingtime;temp_time = ef[zx].jieshutime;ef[zx].run_flag = 1;tc+= 1;ef[zx].order = tc;}return 0;}时间片轮struct ef *input(){int N, i;// 定义队首、队尾struct ef *head, *rear;// p是队尾指针,q是队首指针,t是执行时间struct ef *p, *q, *t;// 初始化队首和队尾为空head = rear = NULL;cout <<"请输入进程数目:"<<endl;cin>> N;for (i = 0; i < N; i++){// 初始化一个空间给进程p = (struct ef *)malloc(sizeof(struct ef));cout <<"请输入第"<< i+1 <<"个进程的名字\n"<<endl;cin >> p->name;cout <<"请输入第"<< i + 1 <<"个进程的编号:\n"<< endl;cin >>p->number;cout <<"请输入第"<< i + 1 <<"个进程的到达时间:\n"<< endl;cin >>p->daodatime;cout <<"请输入第"<< i + 1 <<"个进程的服务时间:\n"<< endl;cin >> p->fuwutime;p->shengyutime = p->fuwutime;p->next = NULL;// 当输入结束时,把p的数据放到队首,以便下一步执行if (rear == NULL){head = p;p->next = NULL;rear = p;}// 否则执行时间为空,队首变成qelse{t = NULL;q = head;// 当q和q的到达时间小于p的到达时间时,把执行时间给qwhile (q && q->daodatime < p->daodatime){t = q;q = q->next;}// 当q是队首时,则下一个队首变成p,以便每个进程都能够得到时间片if (q == head){p->next = head;head = p;}// 当执行时间片到达队尾时(执行完成),返回给队首pelse if (t == rear){rear->next = p;p->next = NULL;rear = p;}// 否则给队首p占用执行时间,p执行完后到qelse{t->next = p;p->next = q;}}}// 返回队首return head;}void run(struct ef *head){struct ef *p, *t, *r;int num;// 运行过程vector<string> vec_out;cout<<"请输入时间片:"<<endl;cin>>num;// 当队首不为空时,把p给队首while (head != NULL){r = p = head;// 把执行时间给队首while (p != NULL){t = head;// p的剩余时间 = 剩余时间 - 时间片p->shengyutime = p->shengyutime - num;p->jieshutime = p->kaishitime + p->fuwutime;string s = p->name;vec_out.push_back(s);// 当p运行完,即剩余时间小于0时,仍然把它当做0处理if (p->shengyutime < 0)p->shengyutime = 0;cout<<"进程编号到达时间服务时间剩余时间完成时间\n"<<endl;//时间不为空时,输出当前进程的信息,并把时间片交给下一个进程while (t != NULL){cout <<" "<< t->name <<" "<<t->number <<" "<<t->daodatime <<" "<< t->fuwutime <<" "<< t->shengyutime <<" "<<t->jieshutime <<endl;t = t->next;}//当队首的剩余时间为0时,先把队首改成p的下一个,然后释放内存,删除队首节点if (p->shengyutime == 0){if (p == head){head = p->next;free(p);p = head;}//否则返回执行,把队尾的下一个指针变成p的下一个指针,队尾的位置移动到队首else{r->next = p->next;p = r->next;r = p;}}//否则把队首的位置给队尾,把队首的状态显示为“就绪”状态else{r = p;p = p->next;}}}cout<<"执行顺序:\n"<<endl;cout << vec_out[0].c_str()<<endl;for (int i = 1; i<vec_out.size(); i++){cout << vec_out[i].c_str()<<endl;}}void yunxing(){//定义时间片的队首结构体struct ef *head;// 队首执行的时间head =input();run(head);}7、程序源代码#include"stdafx.h"#include<iostream>#include<vector>using namespace std;#define MAX 10int c; //实际进程个数int fcfs(); //先来先服务int sjf(); //短作业优先int hrrf(); //响应比高优先int yxj(); //优先级调度int in(); //进程参数输入int out(); //调度结果输出struct ef{char name[10]; //进程名称int number; //进程编号float daodatime; //到达时间float kaishitime; //开始运行时间float yunxingtime; //运行时间float jieshutime; //运行结束时间int shengyutime; // 剩余时间int fuwutime; //服务时间int order; //运行次序int run_flag; //调度标志int priority; //优先级struct ef *next;}ef[MAX];int fcfs() //先来先服务{float tp = 0;int i;int zx;tp = ef[0].daodatime;for (i = 0; i<c; i++){ef[i].kaishitime = tp;ef[i].jieshutime = ef[i].kaishitime + ef[i].yunxingtime;ef[i].run_flag = 1;tp = ef[i].jieshutime;zx = i;ef[zx].order = i + 1;}return 0;}int yxj() //优先级调度{float temp_time = 0;int i = 0, j;int zx, tc;int max_priority;max_priority = ef[i].priority;j = 1;while ((j<c) && (ef[i].daodatime == ef[j].daodatime)){if (ef[j].priority>ef[i].priority){max_priority = ef[j].priority;i = j;}j++;} //查找第一个被调度的进程//对第一个被调度的进程求相应的参数zx = i;ef[zx].kaishitime = ef[zx].kaishitime;ef[zx].jieshutime = ef[zx].kaishitime + ef[zx].yunxingtime;ef[zx].run_flag = 1;temp_time = ef[zx].jieshutime;ef[zx].order = 1;tc = 1;while (tc<c){max_priority = 0;for (j = 0; j<c; j++){if ((ef[j].daodatime <= temp_time) && (!ef[j].run_flag))if (ef[j].priority>max_priority){max_priority = ef[j].priority;zx = j;}}//查找下一个被调度的进程////对找到的下一个被调度的进程求相应的参数ef[zx].kaishitime = temp_time;ef[zx].jieshutime = ef[zx].kaishitime + ef[zx].yunxingtime;ef[zx].run_flag = 1;temp_time = ef[zx].jieshutime;tc++;ef[zx].order = tc;}return 0;}int sjf() //短作业优先{float temp_time = 0;int i = 0, j;int zx, tc;float yunxingtime;yunxingtime = ef[i].yunxingtime;j = 1;while ((j<c) && (ef[i].daodatime == ef[j].daodatime)){if (ef[j].yunxingtime<ef[i].yunxingtime){yunxingtime = ef[j].yunxingtime;i = j;}j++;} //查找第一个被调度的进程//对第一个被调度的进程求相应的参数zx = i;ef[zx].kaishitime = ef[zx].daodatime;ef[zx].jieshutime = ef[zx].kaishitime + ef[zx].yunxingtime;ef[zx].run_flag = 1;temp_time = ef[zx].jieshutime;ef[zx].order = 1;tc = 1;while (tc<c){for (j = 0; j<c; j++){if ((ef[j].daodatime <= temp_time) && (!ef[j].run_flag)){yunxingtime = ef[j].yunxingtime; zx = j; break;}}for (j = 0; j<c; j++){if ((ef[j].daodatime <= temp_time) && (!ef[j].run_flag))if (ef[j].yunxingtime<yunxingtime){yunxingtime = ef[j].yunxingtime;zx= j;}}//查找下一个被调度的进程//对找到的下一个被调度的进程求相应的参数ef[zx].kaishitime = temp_time;ef[zx].jieshutime = ef[zx].kaishitime + ef[zx].yunxingtime;ef[zx].run_flag = 1;temp_time = ef[zx].yunxingtime;tc++;ef[zx].order = tc;}return 0;}int hrrf() //响应比高优先{int j, zx, tc;float temp_time, respond_rate, max_respond_rate;//第一个进程被调度ef[0].kaishitime = ef[0].daodatime;ef[0].jieshutime = ef[0].kaishitime + ef[0].yunxingtime;temp_time = ef[0].jieshutime;ef[0].run_flag = 1;ef[0].order = 1;tc = 1;//调度其他进程while (tc<c){max_respond_rate = 0;for (j = 1; j<c; j++){if ((ef[j].daodatime <= temp_time) && (!ef[j].run_flag)){respond_rate = (temp_time - ef[j].daodatime) / ef[j].yunxingtime;if (respond_rate>max_respond_rate){max_respond_rate = respond_rate;zx = j;}}}//找响应比高的进程ef[zx].kaishitime = temp_time;ef[zx].jieshutime = ef[zx].kaishitime + ef[zx].yunxingtime;temp_time = ef[zx].jieshutime;ef[zx].run_flag = 1;tc+= 1;ef[zx].order = tc;}return 0;}int in() //进程参数输入{int i;cout <<"请输入进程数目:\n"<<endl;cin>>c;for (i = 0; i<c; i++){cout <<"请输入第"<< i+1 <<"个进程的名字\n"<<endl;cin>> ef[i].name;cout <<"请输入第"<< i + 1 <<"个进程的编号:\n"<< endl;cin>> ef[i].number;cout <<"请输入第"<< i + 1 <<"个进程的到达时间:\n"<< endl;cin >> ef[i].daodatime;cout <<"请输入第"<< i + 1 <<"个进程的运行时间:\n"<< endl;cin >> ef[i].yunxingtime;ef[i].kaishitime = 0;ef[i].jieshutime = 0;ef[i].order = 0;ef[i].run_flag = 0;}return 0;}int out() /*调度结果输出*/{int i;float turn_round_time = 0, f1, w = 0;cout<<"进程名编号到达时间运行时间开始时间结束时间平均周转时间平均带权周转时间\n"<<endl;for (i = 0; i<c; i++){f1 = ef[i].jieshutime - ef[i].daodatime;turn_round_time += f1;w += (f1 / ef[i].yunxingtime);cout <<" "<< ef[i].name <<" "<< ef[i].number <<" "<<ef[i].daodatime <<" "<< ef[i].yunxingtime <<" "<< ef[i].kaishitime <<" "<< ef[i].jieshutime <<" "<< turn_round_time / c<<" "<< w / c<<endl;}//cout << "平均周转时间=\n"<<turn_round_time / c<<endl;//cout << "带权周转时间=\n"<< w / c<<endl;return 0;}struct ef *input(){int N, i;// 定义队首、队尾struct ef *head, *rear;// p是队尾指针,q是队首指针,t是执行时间struct ef *p, *q, *t;// 初始化队首和队尾为空head = rear = NULL;cout <<"请输入进程数目:"<<endl;cin>> N;for (i = 0; i < N; i++){// 初始化一个空间给进程p = (struct ef *)malloc(sizeof(struct ef));cout <<"请输入第"<< i+1 <<"个进程的名字\n"<<endl;cin >> p->name;cout <<"请输入第"<< i + 1 <<"个进程的编号:\n"<< endl;cin >>p->number;cout <<"请输入第"<< i + 1 <<"个进程的到达时间:\n"<< endl;cin >>p->daodatime;cout <<"请输入第"<< i + 1 <<"个进程的服务时间:\n"<< endl;cin >> p->fuwutime;p->shengyutime = p->fuwutime;p->next = NULL;// 当输入结束时,把p的数据放到队首,以便下一步执行if (rear == NULL){head = p;p->next = NULL;rear = p;}// 否则执行时间为空,队首变成qelse{t = NULL;q = head;// 当q和q的到达时间小于p的到达时间时,把执行时间给qwhile (q && q->daodatime < p->daodatime){t = q;q = q->next;}// 当q是队首时,则下一个队首变成p,以便每个进程都能够得到时间片if (q == head){p->next = head;head = p;}// 当执行时间片到达队尾时(执行完成),返回给队首pelse if (t == rear){rear->next = p;p->next = NULL;rear = p;}// 否则给队首p占用执行时间,p执行完后到qelse{t->next = p;p->next = q;}}}// 返回队首return head;}void run(struct ef *head){struct ef *p, *t, *r;int num;// 运行过程vector<string> vec_out;cout<<"请输入时间片:"<<endl;cin>>num;// 当队首不为空时,把p给队首while (head != NULL){r = p = head;// 把执行时间给队首while (p != NULL){t = head;// p的剩余时间 = 剩余时间 - 时间片p->shengyutime = p->shengyutime - num;p->jieshutime = p->kaishitime + p->fuwutime;string s = p->name;vec_out.push_back(s);// 当p运行完,即剩余时间小于0时,仍然把它当做0处理if (p->shengyutime < 0)p->shengyutime = 0;cout<<"进程编号到达时间服务时间剩余时间完成时间\n"<<endl;//时间不为空时,输出当前进程的信息,并把时间片交给下一个进程while (t != NULL){cout <<" "<< t->name <<" "<<t->number <<" "<<t->daodatime <<" "<< t->fuwutime <<" "<< t->shengyutime <<" "<<t->jieshutime <<endl;t = t->next;}//当队首的剩余时间为0时,先把队首改成p的下一个,然后释放内存,删除队首节点if (p->shengyutime == 0){if (p == head){head = p->next;free(p);p = head;}//否则返回执行,把队尾的下一个指针变成p的下一个指针,队尾的位置移动到队首else{r->next = p->next;p = r->next;r = p;}}//否则把队首的位置给队尾,把队首的状态显示为“就绪”状态else{r = p;p = p->next;}}}cout<<"执行顺序:\n"<<endl;cout << vec_out[0].c_str()<<endl;for (int i = 1; i<vec_out.size(); i++){cout << vec_out[i].c_str()<<endl;}}void yunxing(){//定义时间片的队首结构体struct ef *head;// 队首执行的时间head =input();run(head);}int main(){int p;cout <<"请选择调度算法:"<< endl;cout <<"1.先来先服务"<< endl;cout <<"2.时间片轮调度"<< endl;cout <<"3.短作业优先"<< endl;cout <<"4.响应比高优先"<< endl;cout <<"5.优先级"<< endl;cout <<"6.退出"<< endl;cin >> p;switch (p){case 6:cout <<"运行结束。
CPU调度算法的模拟实现一、设计目的利用C++编写CPU调度算法,实现先来先服务调度算法FCFS、优先级调度算法PS、短作业优先调度算法SJF、时间片轮转调度算法RR的运行过程和实现的结果,针对模拟进程,利用编写的CPU调度算法对需要运行的进程进行调度。
进行算法评价,计算平均周转时间和平均等待时间。
二、设计要求针对模拟进程,利用CPU调度算法进行调度,最后要进行算法评价,计算平均周转时间和平均等待时间,并且输出调度结果和输出算法评价指标。
调度所需的进程参数由输入产生(手工输入或者随机数产生)。
三、设计说明?CPU调度决策可在如下4种情况环境下发生:(1)当一个进程从运行切换到等待状态(如:I/O请求,或者调用wait等待一个子进程的终止)(2)当一个进程从运行状态切换到就绪状态(如:出现中断)(3)当一个进程从等待状态切换到就绪状态(如:I/O完成)(4)当一个进程终止时对于第1和4两种情况,没有选择而只有调度。
一个新进程(如果就绪队列中已有一个进程存在)必须被选择执行。
对于第2和第3两种情况,可以进行选择。
当调度只能发生在第1和4两种情况下时,称调度是非抢占的(nonpreemptive)或协作的(cooperative);否则,称调度方案为抢占的(preemptive)。
采用非抢占调度,一旦CPU分配给一个进程,那么该进程会一直使用CPU直到进程终止或切换到等待状态。
抢占调度对访问共享数据是有代价(如加锁)的,有可能产生错误,需要新的机制(如,同步)来协调对共享数据的访问。
抢占对于操作系统内核的设计也有影响。
在处理系统调用时,内核可能忙于进程活动。
这些活动可能涉及要改变重要内核数据(如I/O队列)。
因为根据定义中断能随时发生,而且不能总是被内核所忽视,所以受中断影响的代码段必须加以保护以避免同时访问。
操作系统需要在任何时候都能够接收中断,否则输入会丢失或输出会被改写。
为了这些代码段不被多个进程同时访问,在进入时就要禁止中断,而在退出时要重新允许中断。
调度准则为了比较CPU调度算法所提出的准则:CPU使用率: 需要使CPU尽可能忙吞吐量: 指一个时间单元内所完成进程的数量周转时间:从进程提交到进程完成的时间段称为周转时间,周转时间是所有时间段之和,包括等待进入内存、在就绪队列中等待、在CPU上执行和I/O执行平均周转时间:即周转时间的算数平均值等待时间: 在就绪队列中等待所花费时间之和平均等待时间: 即等待时间的算数平均值响应时间: 从提交请求到产生第一响应的时间。
需要使CPU使用率和吞吐量最大化,而使周转时间、等待时间和响应时间最小化。
绝大多数情况下需要优化平均值,有时需要优化最大值或最小值,而不是平均值四、详细设计4.1先到先服务调度(First-Come,First-Served scheduling)最简单的CPU调度算法是先到先服务算法(First-Come,First-Served scheduling):先请求CPU的进程先分配到CPU。
FCFS策略可以用FIFO队列来容易实现。
当一个进程进入就绪队列,其PCB链接到队列的尾部。
当CPU空闲时,CPU分配给位于队列头的进程,接着运行进程从队列中删除。
FCFS策略的代码编写简单且容易理解,不过采用FCFS策略的平均等待时间通常比较长。
当进程CPU区间时间变化很大,平均等待时间会变化很大。
算法原理:假设有n个进程分别在T1, ? ,Tn时刻到达系统,它们需要的服务时间分别为S1, ? ,Sn。
分别采用先来先服务FCFS调度算法进行调度,计算每个进程的完成时间,周转时间和带权周转时间,并且统计n个进程的平均周转时间和平均带权周转时间。
程序要求如下:1)进程个数n ;每个进程的到达时间T1, ? ,Tn 和服务时间S1, ? ,Sn 。
2)要求采用先来先服务FCFS 调度进程运行,计算每个进程的周转时间,带权周转时间,并且计算所有进程的平均周转时间,带权平均周转时间; 3)输出:要求模拟整个调度过程,输出每个时刻的进程运行状态,如“时刻3:进程B 开始运行”等等;4)输出:要求输出计算出来的每个进程的周转时间,带权周转时间,所有进程的平均周转时间,带权平均周转时间。
实现简要过程: 1)变量初始化;2)接收用户输入n ,T1, ? ,Tn ,S1, ? ,Sn ;3)按照选择算法进行进程调度,计算进程的完成时间、周转时 间和带权周转时间;4)按格式输出调度结果。
测试结果: 案例分析:如果按照P1P2P3顺序到达,Gantt 图如下:0 2427 30平均等待时间:(0+24+27)÷3=17 平均周转时间:(24+27+30)÷3=27如果按照P2P3P1顺序到达,平均等待时间:(0+3+6)÷3=3平均周转时间:(3+6+30)÷3=13另外考虑在动态情况下的性能,假设有一个CPU约束进程和许多I/O约束进程,CPU约束进程会移回到就绪队列并被分配到CPU。
再次所有I/O进程会在就绪队列中等待CPU进程的完成。
由于所有其他进程都等待一个大进程释放CPU,这称之为护航效果(convoy effect)。
与让较短进程最先执行相比,这样会导致CPU和设备使用率变的很低。
FCFS调度算法是非抢占的。
对于分时系统(每个用户需要定时的等待一定的CPU时间)是特别麻烦。
允许一个进程保持CPU时间过长是个严重错误。
4.2 优先级调度(priority scheduling algorithm)算法:每个进程有一个进程控制块(PCB)表示。
进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。
进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。
进程的到达时间为进程输入的时间。
进程的运行时间以时间片为单位进行计算。
每个进程的状态可以是就绪W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。
就绪进程获得CPU后都只能运行一个时间片。
用已占用CPU时间加1来表示。
如果运行一个时间片后,进程的已占用CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。
每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。
重复以上过程,直到所要进程都完成为止。
SJF算法可作为通用的优先级调度算法的一个特例。
每个进程都有一个优先级与其关联,具有最高优先级的进程会分配到CPU。
具有相同优先级的进程按FCFS顺序调度。
SJF,其优先级(p)为下一个CPU区间的倒数。
CPU区间越大,则优先级越小,反之亦然。
优先级通常是固定区间的数字,如0~7,但是数字大小与优先级的高低没有定论。
测试结果:案例分析:(假设数字越小优先级越高)画出Gantt图:0 1 6 16 1819平均等待时间:(0+1+6+16+18)÷5=8.2平均周转时间:(1+6+16+18+19)÷5=12优先级可通过内部或外部方式来定义。
内部定义优先级使用一些测量数据以计算进程优先级。
外部优先级是通过操作系统之外的准则来定义,如进程重要性等。
优先级调度可以是抢占的或非抢占的。
优先级调度算法的一个重要问题是无限阻塞(indefinite blocking)或饥饿(starvation)。
可以运行但缺乏CPU的进程可认为是阻塞的,它在等待CPU。
优先级调度算法会使某个有低优先级无穷等待CPU。
低优先级进程务求等待问题的解决之一是老化(aging)。
老化是一种技术,以逐渐增加在系统中等待很长时间的进程的优先级。
4.3 时间片轮转调度算法(round-robin,RR)专门为分时系统设计。
它类似于FCFS调度,但是增加了抢占以切换进程。
定义一个较小的时间单元,称为时间片(time quantum,or time slice)。
将就绪队列作为循环队列。
CPU调度程序循环就绪队列,为每个进程分配不超过一个时间片段的CPU。
系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片。
时间片的大小从几ms到几百ms。
当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。
如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。
如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。
调度程序所要做的就是维护一张就绪进程列表,当进程用完它的时间片后,它被移到队列的末尾。
RR策略的平均等待时间通常较长测试结果:案例分析:(使用4ms时间片)画出Gantt图:0 4 7 10 14 18 22 26 30 平均等待时间:[0+4+7+(10-4)]÷3=5.66平均周转时间:(7+10+30)÷3=15.67如果就绪,那么每个进程会得到1n的CPU时间,其长度不超过q时间单元。
每个进程必须等待CPU时间不会超过(n?1)×q个时间单元,直到它的下一个时间片为止。
RR算法的性能很大程度上依赖于时间片的大小。
在极端情况下,如果时间片非常大,那么RR算法与FCFS算法一样。
如果时间片很小,那么RR算法称为处理器共享,n个进程对于用户都有它自己的处理器,速度为真正处理器速度的1/n。
小的时间片会增加上下文切换的次数,因此,希望时间片比上下文切换时间长,事实上,绝大多数现代操作系统,上下文切换的时间仅占时间片的一小部分。
周转时间也依赖于时间片的大小。
4.4 最短作业优先调度(shortest-job-first scheduling,SJF)将每个进程与下一个CPU区间段相关联。
当CPU为空闲时,它会赋给具有最短CPU区间的进程。
如果两个进程具有同样长度,那么可以使用FCFS调度来处理。
注意,一个更为适当地表示是最短下一个CPU区间的算法,这是因为调度检查进程的下一个CPU区间的长度,而不是其总长度。
?这种策略是下一次选择所需处理时间最短的进程。
是非抢占策略,目的也是为减少FCFS策略对长进程的偏向。
测试结果:案例分析:画出Gantt图:0 3 9 16 24 SJF平均等待时间:(0+3+9+16)÷4=7SJF平均周转时间:(3+9+16+24)÷4=13FCFS平均等待时间:(0+6+14+21)÷4=10.25FCFS平均周转时间:(6+14+21+24)÷4=16.25SJF算法的平均等待时间最小。